Skip to content

integrations:posthog:connect creates an org and project before any confirmation, with no way to use an existing PostHog project #4273

Description

@designorant

Summary

Two related gaps in eas integrations:posthog:connect:

  1. It creates a PostHog organization and project before any confirmation. The only prompt beforehand is region selection.
  2. There is no way to point the connection at a pre-existing PostHog project.

Together these mean a developer who already uses PostHog, and whose PostHog account email differs from their Expo account email, gets a brand-new PostHog account, organization, and project created for them — with no opportunity to say "use the project I already have," and no chance to decline before the resources exist.

To be clear about scope: the command does prompt before overwriting EXPO_PUBLIC_POSTHOG_* in .env.local and in EAS, so existing configuration is not silently replaced. The problem is confined to the provisioning step, which happens earlier and unconditionally.

Why it happens

In build/commands/integrations/posthog/connect.js (eas-cli 22.3.0), the project mutation accepts no project selector:

project = await PostHogMutation.setupPostHogProjectAsync(graphqlClient, {
  appId: projectId,
  posthogOrganizationConnectionId: connection.id,
})

and the lookup only finds a project EAS previously created for that app:

let project = await PostHogQuery.getPostHogProjectByAppIdAsync(graphqlClient, projectId)

There is an org-level reuse path, but it is gated on email identity:

throw new Error(`The email on the ${account.name} account already has a PostHog account,
  which must be connected by approving it in a browser. ...`)

If the Expo account's email has no PostHog account, the server takes the create branch. So a developer whose PostHog login differs from their Expo login always gets new resources. Even the browser-approval branch reuses only the organization — the project is still newly created.

Managed or bare?

Bare — native directories are committed. Not relevant to the failure; the command never reaches native code.

Environment

  • eas-cli 22.3.0, darwin-arm64, node 22.22.0
  • Expo SDK 54, pnpm workspace monorepo
  • PostHog EU Cloud

Reproducible steps to reproduce from a blank project

  1. Create a PostHog project manually and note that its account email differs from your Expo account email.
  2. Run eas integrations:posthog:connect and select a region.

Observed:

✔ Select a PostHog region › European Union (EU)
✔ Created PostHog organization <account>-XXXXXXXX
✔ Created PostHog project <App Name>
? PostHog features to set up ›

The organization and project already exist by the time the first feature prompt appears. Aborting here (Ctrl-C) leaves them behind.

Expected behavior

Either of these would resolve it:

  1. Confirm before provisioning. e.g. No PostHog account found for <email>. Create a new organization and project? (y/N). This matters more than a typical confirmation because the CLI cannot undo it: eas integrations:posthog:disconnect removes only the EAS-side link record, and the created organization must then be deleted in the PostHog UI — under an account auto-created for the Expo account's email, which the developer may not realize exists or have credentials for.

  2. Allow using an existing project. A prompt to select from the connected organization's projects, and/or --posthog-project-id / --posthog-organization-id flags for the non-interactive case.

Note on the docs

https://docs.expo.dev/guides/using-posthog/ says "Re-running connect is safe: it reuses your existing organization and project." In context this means "what EAS previously created," but it reads naturally as "it will find the PostHog project I already have" — which is what led me to run the command expecting a link rather than a provision.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions