coleam00/Archon · error

OAuth provider '${oauthAuth.name}' requested a manual code b

Error message

OAuth provider '${oauthAuth.name}' requested a manual code but no onManualCodeInput callback was supplied.

What it means

adaptLoginCallbacks wraps caller-supplied callbacks into the Pi SDK's ProviderAuthInteraction. When the OAuth flow reaches a prompt of type 'manual_code' (the provider requires the user to paste a code/device code manually) but the caller passed no onManualCodeInput callback, there is no way to obtain the code, so login aborts with this error instead of hanging.

Source

Thrown at packages/providers/src/oauth.ts:128

    credentials: OAuthCredential,
    options?: { signal?: AbortSignal }
  ): Promise<OAuthCredential>;
  getApiKey(credentials: OAuthCredential): Promise<{ apiKey: string }>;
}

/* ─── Adapter: `OAuthAuth` (pi-ai ≥ 0.84) → legacy callback-driven surface ── */

/** Map the SDK's `interaction` prompts/events onto the legacy callbacks. */
function adaptLoginCallbacks(
  oauthAuth: OAuthAuth,
  callbacks: OAuthLoginCallbacks
): ProviderAuthInteraction {
  return {
    signal: callbacks.signal ?? new AbortController().signal,
    prompt: async (prompt: AuthPrompt): Promise<string> => {
      if (prompt.type === 'manual_code') {
        if (!callbacks.onManualCodeInput) {
          throw new Error(
            `OAuth provider '${oauthAuth.name}' requested a manual code but no onManualCodeInput callback was supplied.`
          );
        }
        return callbacks.onManualCodeInput();
      }
      if (prompt.type === 'select') {
        return (await callbacks.onSelect({ options: prompt.options })) ?? '';
      }
      // text / secret — Pi uses these for one-off prompts (e.g. github-copilot
      // enterprise domain). The caller decides how to answer; the Archon
      // bridge has no interactive channel and returns "" (blank default).
      return callbacks.onPrompt(prompt);
    },
    notify: (event: AuthEvent): void => {
      if (event.type === 'auth_url') {
        callbacks.onAuth({ url: event.url, instructions: event.instructions });
        return;
      }

View on GitHub (pinned to 0773b97458)

Solutions

  1. Pass an onManualCodeInput callback in the callbacks object that prompts the user (or reads stdin) and returns the code
  2. Run the login in an environment that supports the automatic browser flow so no manual code is requested
  3. For automation, pre-provision credentials instead of running the interactive login flow

Example fix

// before
await login('anthropic', { signal });
// after
await login('anthropic', {
  signal,
  onManualCodeInput: async () => {
    const code = await promptUser('Enter the code: ');
    return code;
  }
});
Defensive patterns

Strategy: validation

Validate before calling

if (typeof callbacks?.onManualCodeInput !== 'function') {
  throw new Error('login() requires onManualCodeInput for providers with manual code flows');
}

Type guard

function hasManualCodeInput(
  c: ProviderLoginCallbacks
): c is ProviderLoginCallbacks & Required<Pick<ProviderLoginCallbacks, 'onManualCodeInput'>> {
  return typeof c.onManualCodeInput === 'function';
}

Try / catch

try {
  await login(providerId, callbacks);
} catch (err) {
  if (String(err.message).includes('manual code')) {
    console.error('Re-run login with an onManualCodeInput callback.');
  }
  throw err;
}

Prevention

When it happens

Trigger: Calling login() for a provider whose oauthAuth flow emits a manual_code AuthPrompt while the callbacks argument omitted onManualCodeInput.

Common situations: Headless/CI logins for providers that fall back to device-code or manual paste flows; interactive OAuth unavailable so Pi downgrades to manual code entry; caller assumed a fully automatic browser flow and didn't wire the callback.

Related errors


AI-assisted analysis of coleam00/Archon@0773b97458 (2026-09-01). Data as JSON: /api/errors/a34d979b53d1f209. Report an issue: GitHub.