nexu-io/open-design · error · Error
could not discover OAuth metadata for ${issuer}
Error message
could not discover OAuth metadata for ${issuer} What it means
beginAuth Step 2 calls discoverAuthServer(issuer) and throws if it returns null, meaning no valid OAuth Authorization Server metadata could be fetched or parsed at the issuer (the /.well-known/oauth-authorization-server or RFC8414 fallback). Step 1 may have derived the issuer from the resource origin when the server published no protected-resource metadata.
Source
Thrown at apps/daemon/src/mcp-oauth.ts:553
* correct authorize URL, and (b) finish the flow when the callback hits.
*/
export async function beginAuth(
input: BeginAuthInput,
): Promise<BeginAuthResult> {
const fetchImpl = input.fetchImpl ?? fetch;
// Step 1: ask the MCP server who its auth server is. If the server
// doesn't publish protected-resource metadata, fall back to assuming
// the resource origin IS the auth server — most "stand-alone" MCP
// providers (Higgsfield etc.) host both at the same host.
const prm = await discoverProtectedResource(input.serverUrl, fetchImpl);
const issuerHint = prm?.authorization_servers?.[0];
const issuer = issuerHint ?? new URL(input.serverUrl).origin;
// Step 2: discovery on the auth server.
const authServer = await discoverAuthServer(issuer, fetchImpl);
if (!authServer) {
throw new Error(`could not discover OAuth metadata for ${issuer}`);
}
// Step 3: ensure we have a registered client_id (DCR if missing).
const client = await getOrRegisterClient(
input.dataDir,
authServer,
input.redirectUri,
fetchImpl,
);
// Step 4: PKCE + state.
const codeVerifier = generateCodeVerifier();
const codeChallenge = deriveCodeChallenge(codeVerifier);
const state = generateState();
const scope =
input.scope ??
(Array.isArray(prm?.scopes_supported) && prm!.scopes_supported!.length > 0View on GitHub (pinned to 5be4028344)
Solutions
- Confirm serverUrl is correct and the auth server is discoverable at its issuer.
- Ensure the MCP server publishes protected-resource metadata pointing at the real auth server via authorization_servers.
- Check network or proxy access to /.well-known/oauth-authorization-server.
Defensive patterns
Strategy: try-catch
Validate before calling
const issuer = new URL(serverUrl).origin;
const meta = await discoverAuthServer(issuer);
if (!meta) {
throw new Error('no OAuth metadata reachable; verify serverUrl and protected-resource metadata');
} Try / catch
try {
await beginAuth(input);
} catch (e) {
if (/could not discover OAuth metadata/i.test(e.message)) {
// verify serverUrl; ensure protected-resource metadata advertises the auth server
surfaceToUser('Check the MCP server URL and its auth server discovery.');
}
throw e;
} Prevention
- Validate serverUrl before starting the OAuth flow.
- Confirm the provider publishes protected-resource metadata when auth lives on another host.
- Ensure network access to /.well-known/oauth-authorization-server.
When it happens
Trigger: The issuer is unreachable or is not an auth server; the well-known endpoint returns 404; the metadata JSON is malformed; the MCP server's origin is not its auth server and no authorization_servers hint was published.
Common situations: A provider hosts auth on a different host but did not publish protected-resource metadata; a typo in serverUrl; a corporate network blocks the well-known path.
Related errors
- dynamic client registration failed: HTTP ${res.status} ${res
- token endpoint rejected request: HTTP ${res.status} ${res.st
- Could not fetch ${url} — the site may block server-side requ
- invalid brand asset url: ${String(url)}
- blocked non-public brand asset host: ${host}
AI-assisted analysis of nexu-io/open-design@5be4028344 (2026-08-12).
Data as JSON: /api/errors/c85ecded4a9dfb72.
Report an issue: GitHub.