tinyhumansai/openhuman · warning
mcp.connectAuth.oauthTimeout
Error message
mcp.connectAuth.oauthTimeout
What it means
MCP OAuth connect flow: after opening the provider's authorize URL in the system browser, the modal polls mcpClientsApi.status() every 2.5s for up to 180s waiting for that server to report 'connected' (the OAuth callback completing core-side). Past 3 minutes it gives up with this localized timeout message.
Source
Thrown at app/src/components/channels/mcp/ConnectAuthModal.tsx:297
setBusy(true);
setError(null);
setOauthWaiting(true);
void (async () => {
try {
const url = await mcpClientsApi.oauthBegin(server.server_id);
await openUrl(url);
const started = Date.now();
const poll = async (): Promise<void> => {
const statuses = await mcpClientsApi.status();
const mine = statuses.find(s => s.server_id === server.server_id);
if (mine?.status === 'connected') {
const result = await mcpClientsApi.connect(server.server_id);
onConnected(result.tools ?? []);
onClose();
return;
}
if (Date.now() - started > 180000) {
throw new Error(t('mcp.connectAuth.oauthTimeout'));
}
window.setTimeout(() => {
void poll().catch(handlePollError);
}, 2500);
};
const handlePollError = (err: unknown) => {
setError(err instanceof Error ? err.message : String(err));
setOauthWaiting(false);
setBusy(false);
};
await poll().catch(handlePollError);
} catch (err) {
const msg = err instanceof Error ? err.message : String(err);
log('oauth failed: %s', msg);
setError(msg);
setOauthWaiting(false);
setBusy(false);
}View on GitHub (pinned to a221052e0d)
Solutions
- Retry the connect flow and complete consent promptly in the opened browser tab
- Confirm the authorize URL actually opened (openUrl) and that the MCP server's redirect URI is correctly registered
- After a timeout, check the server's status in the MCP list — if it shows connected, call connect again instead of re-authenticating
Defensive patterns
Strategy: retry
Validate before calling
// Before declaring timeout, do one final authoritative status check:
const statuses = await mcpClientsApi.status();
const mine = statuses.find(s => s.server_id === id);
const connected = mine?.status === 'connected';
if (!connected) { /* only now show the timeout error */ } Type guard
const isConnected = (s: { status?: string } | undefined): boolean =>
s?.status === 'connected'; Try / catch
try {
await pollUntilConnected(serverId, 180_000);
} catch (e) {
if (e instanceof Error && e.message === t('mcp.connectAuth.oauthTimeout')) {
// keep modal open, offer Retry — re-auth is often all that is needed
setOauthWaiting(false);
return;
}
throw e;
} Prevention
- Complete the consent screen promptly after the browser tab opens
- Register loopback redirect URIs correctly on the MCP provider's OAuth client
- On timeout, check the server list first — a late callback may have connected it
When it happens
Trigger: User never completes consent in the browser; the OAuth callback never reaches the core (redirect URI misconfigured, wrong browser account); server needs longer than 180s to become connected; polling error path ends the wait early.
Common situations: Browser blocked or user abandoned the consent tab; MCP server's OAuth client not registered for the loopback redirect; slow provider authorization backends.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- OPENAI_CODEX_OAUTH_MISSING_AUTH_URL
- OPENAI_CODEX_OAUTH_MISSING_CALLBACK_URL
- Request timed out. Please try again.
- Discord link complete response missing required boolean fiel
- Core RPC ${payload.method} timed out after ${effectiveTimeou
AI-assisted analysis of tinyhumansai/openhuman@a221052e0d (2026-08-16).
Data as JSON: /api/errors/f5457625d8ada390.
Report an issue: GitHub.