coleam00/Archon · error

Pi OAuth provider '${oauthAuth.name}' produced no apiKey for

Error message

Pi OAuth provider '${oauthAuth.name}' produced no apiKey for the stored credential.

What it means

getApiKey derives fresh auth state from a stored credential via the provider's oauthAuth.toAuth(). toAuth is a pure derivation and does not check expiry, so an apiKey can legitimately be absent — e.g. the stored credentials are incomplete, expired past refresh, or the provider returned no token. The method throws rather than returning an unusable empty key.

Source

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

  return {
    id,
    usesCallbackServer,
    async login(callbacks): Promise<OAuthCredential> {
      const oauthAuth = await loader();
      return oauthAuth.login(adaptLoginCallbacks(oauthAuth, callbacks));
    },
    async refreshToken(credentials, options): Promise<OAuthCredential> {
      const oauthAuth = await loader();
      const signal = options?.signal ?? new AbortController().signal;
      return oauthAuth.refresh(credentials, signal);
    },
    async getApiKey(credentials): Promise<{ apiKey: string }> {
      const oauthAuth = await loader();
      // toAuth is a side-effect-free derivation ({ apiKey?, headers?, baseUrl? })
      // from whatever credential it is given — it does NOT check expiry.
      const auth = await oauthAuth.toAuth(credentials);
      if (!auth.apiKey) {
        throw new Error(
          `Pi OAuth provider '${oauthAuth.name}' produced no apiKey for the stored credential.`
        );
      }
      return { apiKey: auth.apiKey };
    },
  };
}

export const anthropicOAuthProvider: OAuthProviderInterface = adaptOAuthAuth(
  'anthropic',
  () => loadOAuthAuth('anthropic.js', 'anthropicOAuth'),
  true
);
export const githubCopilotOAuthProvider: OAuthProviderInterface = adaptOAuthAuth(
  'github-copilot',
  () => loadOAuthAuth('github-copilot.js', 'githubCopilotOAuth'),
  false
);

View on GitHub (pinned to 0773b97458)

Solutions

  1. Delete the stored credential and re-run the provider's login flow to obtain fresh tokens
  2. Inspect the stored credentials for missing/expired fields and refresh them explicitly before calling getApiKey
  3. Verify the installed Pi SDK version matches the adapter (toAuth behavior may have changed)
  4. Check provider-side account status (revoked grants, expired sessions) and re-authorize

Example fix

// before (stale stored credentials)
const { apiKey } = await provider.getApiKey(staleCredentials);
// after (re-login when derivation yields nothing)
let creds = staleCredentials;
const auth = await oauthAuth.toAuth(creds);
if (!auth.apiKey) creds = await login(providerId, callbacks);
const { apiKey } = await provider.getApiKey(creds);
Defensive patterns

Strategy: try-catch

Validate before calling

const auth = await oauthAuth.toAuth(credentials);
const needsRelogin = !auth.apiKey;

Type guard

function hasApiKey(a: { apiKey?: string }): a is { apiKey: string } {
  return typeof a.apiKey === 'string' && a.apiKey.length > 0;
}

Try / catch

try {
  return await provider.getApiKey(credentials);
} catch (err) {
  if (String(err.message).includes('produced no apiKey')) {
    const fresh = await runLogin(providerId); // re-authenticate
    return provider.getApiKey(fresh);
  }
  throw err;
}

Prevention

When it happens

Trigger: getApiKey(credentials) is invoked with a stored OAuth credential for which toAuth() returns an object with no apiKey (refresh failed to yield a token, credentials shape changed, or provider returned partial auth state).

Common situations: Long-lived stored credentials expired beyond refresh window; provider rotated its token response shape after an SDK update; credentials persisted by an older version missing fields the new toAuth expects; corrupted/partial credential row in the store.

Related errors


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