NousResearch/hermes-agent · error · Error
OAuth failed to start
Error message
OAuth failed to start
What it means
This is the fallback message when start(serverName) — the backend call that initiates the MCP server's OAuth flow — returns `{status: 'error'}` with an empty or missing `error` field. The backend rejected the flow start but gave no reason, so the client shows the generic text. The popup is closed and the error rethrown.
Source
Thrown at web/src/lib/mcp-dashboard-oauth.ts:34
serverName,
start,
status,
open,
sleep = defaultSleep,
maxPollFailures = 3,
}: CompleteOptions): Promise<McpOAuthFlow> {
// Open synchronously from the click handler, before the first await. Browsers
// otherwise classify the later OAuth popup as unsolicited and block it.
const authWindow = open("about:blank", "_blank") as Window | null;
if (!authWindow) {
throw new Error("OAuth popup was blocked — allow popups for this dashboard and retry");
}
authWindow.opener = null;
let started: McpOAuthFlow;
try {
started = await start(serverName);
if (started.status === "error") {
throw new Error(started.error || "OAuth failed to start");
}
if (!started.authorization_url) {
throw new Error("OAuth server did not provide an authorization URL");
}
authWindow.location.href = started.authorization_url;
} catch (error) {
authWindow.close();
throw error;
}
let pollFailures = 0;
for (;;) {
let current: McpOAuthFlow;
try {
current = await status(started.flow_id);
pollFailures = 0;
} catch (error) {
pollFailures += 1;View on GitHub (pinned to c896c09c42)
Solutions
- Check the gateway logs at the moment of the failed start — the server-side exception carries the real reason the client didn't receive.
- Verify the MCP server's OAuth config (issuer/client metadata) is complete and the server is reachable from the gateway.
- Update the gateway so its start endpoint includes a descriptive `error` field, making future failures self-explanatory.
Defensive patterns
Strategy: try-catch
Type guard
function isStartError(r: unknown): r is { status: 'error'; error?: string } {
return !!r && (r as { status?: string }).status === 'error'
} Try / catch
try {
await completeMcpDashboardOAuth({ serverName, start, status, open })
} catch (err) {
if (String(err) === 'OAuth failed to start') {
toast('Gateway refused the OAuth start — check gateway logs for this server')
}
throw err
} Prevention
- Correlate failures with gateway logs using the server name and timestamp.
- Verify OAuth client metadata is configured before offering the OAuth button.
- Improve the backend to always include a descriptive error field.
When it happens
Trigger: POSTing the MCP OAuth start endpoint for a server with no OAuth metadata configured, a server entry whose client_id is missing, or a gateway-side OAuth handler that fails before producing an authorization URL but returns an error response without a message.
Common situations: Adding an MCP server whose OAuth client credentials were never configured; gateway version skew where the start endpoint exists but errors; a server marked for OAuth that actually uses no auth.
Related errors
- OAuth popup was blocked — allow popups for this dashboard an
- OAuth server did not provide an authorization URL
- OAuth authorization failed
- OAuth authorization window was closed before completion
- File uploads are not supported against OAuth-gated remote ba
AI-assisted analysis of NousResearch/hermes-agent@c896c09c42 (2026-08-14).
Data as JSON: /api/errors/4982f4415ff58a8d.
Report an issue: GitHub.