Skip to content

Failed team lookup during login is reported as a successful sign-in #476

Description

@beardthelion

What happens

If the team lookup fails during fx login, the sign-in reports success and quietly gives you a session scoped to your personal account.

There is no way to tell it happened. Against a fake issuer returning 500 for /v2/teams:

  • exit code 0
  • stdout byte-identical to a healthy login, including Signed in to Vercel.
  • stderr empty
  • auth.json written with no team_slug and no team_id

A healthy login and a broken one differ only by two absent fields in a file most people never open.

Why it matters

Credential.gatewayTeam() returns null without those fields, so no teamId is attached to gateway requests. The comment on fetchCreditsWithFetch in src/builtins/gateway.zig says /v1/credits "rejects it outright unless the request names one", and team-scoped private models stop being visible. The session persists that way, so it stays broken until the next login.

Cause

Both sign-in paths in src/core/auth/login_flow.zig do:

var teams = fetchTeams(alloc, token.access_token, issuer_url) catch std.ArrayList(Team).empty;

once in completeSignIn (the in-app sign-in) and once in runLogin (the CLI). Every failure collapses into an empty list, which is exactly what an account with genuinely no teams produces, so nothing downstream can tell the two apart. selectTeam returns null for an empty list, no picker appears, and the success message prints unconditionally.

A related case reaches the same end without any error at all: parseTeams skips entries whose id or slug is not a string, so a 200 whose entries drift from the expected shape also yields an empty list, silently.

Reproduce

Point FX_E2E_OAUTH_ISSUER_URL at a local issuer that serves the OAuth device flow normally but returns 500 for /v2/teams, then run fx login. Compare stdout and ~/.fx/auth.json against the same run where /v2/teams returns a team. A 200 with body {"teams":[{"id":123,"slug":"acme"}]} reproduces the silent variant.

Note

The sibling path treats this failure as significant: loadTeamSelection, used by fx teams, calls the same fetchTeams with try and fails loudly. Only the sign-in paths swallow it.

I have a fix and will open a PR shortly.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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