{"record":{"id":"e713699bf577da0a","repo":"can1357/oh-my-pi","slug":"oauth-authorization-failed-please-check-your-clie","errorCode":null,"errorMessage":"OAuth authorization failed. Please check your client credentials.","messagePattern":"OAuth authorization failed\\. Please check your client credentials\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/modes/controllers/mcp-command-controller.ts","lineNumber":1034,"sourceCode":"\t\t\t\tcredentialId,\n\t\t\t\tclientId: flow.resolvedClientId,\n\t\t\t\tresource: flow.resource,\n\t\t\t};\n\t\t} catch (error) {\n\t\t\t// Esc, an external abort, or a newer MCP flow are neutral\n\t\t\t// cancellations. The timeout path also aborts the controller but does\n\t\t\t// not set this flag, so it remains a surfaced error.\n\t\t\tif (cancellationRequested) {\n\t\t\t\tthrow new MCPOAuthCancelledError();\n\t\t\t}\n\n\t\t\tconst errorMsg = error instanceof Error ? error.message : String(error);\n\n\t\t\t// Provide helpful error messages based on failure type\n\t\t\tif (errorMsg.includes(\"timeout\") || errorMsg.includes(\"timed out\")) {\n\t\t\t\tthrow new Error(\"OAuth flow timed out. Please try again.\");\n\t\t\t} else if (errorMsg.includes(\"403\") || errorMsg.includes(\"unauthorized\")) {\n\t\t\t\tthrow new Error(\"OAuth authorization failed. Please check your client credentials.\");\n\t\t\t} else if (errorMsg.includes(\"invalid_grant\")) {\n\t\t\t\tthrow new Error(\"OAuth authorization code is invalid or expired. Please try again.\");\n\t\t\t} else if (errorMsg.includes(\"ECONNREFUSED\") || errorMsg.includes(\"fetch failed\")) {\n\t\t\t\tthrow new Error(\"Could not connect to OAuth server. Please check the URLs and your network connection.\");\n\t\t\t} else {\n\t\t\t\tthrow new Error(`OAuth authentication failed: ${errorMsg}`);\n\t\t\t}\n\t\t} finally {\n\t\t\tthis.ctx.editor.onEscape = originalOnEscape;\n\t\t\texternalSignal?.removeEventListener(\"abort\", onExternalAbort);\n\t\t\tmanualInputClaim?.clear(\"Manual MCP OAuth input cleared\");\n\t\t\tflowClaim.release();\n\t\t}\n\t}\n\n\t/**\n\t * Fold a completed OAuth flow back into a server config. Owns the\n\t * persistence policy in one place: the auth block records the credential","sourceCodeStart":1016,"sourceCodeEnd":1052,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/modes/controllers/mcp-command-controller.ts#L1016-L1052","documentation":"The MCP OAuth flow failed with an error message containing '403' or 'unauthorized', mapped to this message. It means the authorization/token server rejected the client — typically bad client_id/client_secret or missing permissions — rather than a network or user-timing problem.","triggerScenarios":"Token exchange returns HTTP 403; server responds with 'unauthorized' because the client credentials are wrong, the client is not registered for the requested scopes, or the redirect URI is not allowlisted.","commonSituations":"Copy-pasted client_id/client_secret with a typo or stale values; provider rotated the secret; confidential client configured where a public (PKCE) client is required; scope not granted to the app registration.","solutions":["Verify client_id and client_secret are correct and current in the MCP OAuth config","Re-register or update the OAuth app so the requested scopes and redirect URI are allowed","Confirm whether the provider requires a public PKCE client instead of a secret-based client","Retry the flow after fixing credentials"],"exampleFix":"// before\nclientSecret: \"sk-old-rotated-secret\"\n// after\nclientSecret: \"sk-current-secret-from-provider-dashboard\"","handlingStrategy":"validation","validationCode":"// Validate credentials are non-empty and well-formed before the flow\nif (!clientId?.trim() || !clientSecret?.trim()) {\n  throw new Error('OAuth client_id and client_secret are required for this provider');\n}","typeGuard":null,"tryCatchPattern":"try {\n  await runMcpOAuthFlow();\n} catch (err) {\n  if (err instanceof Error && err.message.includes('client credentials')) {\n    // prompt user to re-enter/rotate client_id/client_secret\n  }\n}","preventionTips":["Store client credentials in config/env, verify after provider secret rotations","Confirm the OAuth app registration allows your redirect URI and requested scopes","Use PKCE/public clients where the provider does not support secrets"],"tags":["oauth","auth-failure","mcp","credentials"],"backgroundTag":"oauth-client-unauthorized","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}