nexu-io/open-design · error · Error
dynamic client registration failed: HTTP ${res.status} ${res
Error message
dynamic client registration failed: HTTP ${res.status} ${res.statusText} ${txt} What it means
registerClient POSTs a Dynamic Client Registration (DCR) request to the auth server's registration_endpoint. Any non-2xx response is surfaced as a failure along with status, statusText, and up to 500 chars of body. Causes range from the endpoint rejecting DCR (4xx) to network or server errors (5xx).
Source
Thrown at apps/daemon/src/mcp-oauth.ts:269
const body = {
redirect_uris: [redirectUri],
token_endpoint_auth_method: 'none',
grant_types: ['authorization_code', 'refresh_token'],
response_types: ['code'],
client_name: 'Open Design',
application_type: 'web',
};
const res = await fetchImpl(registrationEndpoint, {
method: 'POST',
headers: {
'content-type': 'application/json',
accept: 'application/json',
},
body: JSON.stringify(body),
});
if (!res.ok) {
const txt = await safeText(res);
throw new Error(
`dynamic client registration failed: HTTP ${res.status} ${res.statusText} ${txt}`,
);
}
const json = (await res.json()) as { client_id?: string; client_secret?: string };
if (!json.client_id) {
throw new Error('dynamic client registration response missing client_id');
}
const out: { clientId: string; clientSecret?: string } = { clientId: json.client_id };
if (json.client_secret) out.clientSecret = json.client_secret;
return out;
}
/**
* Cached version of `registerClient`. Looks up `(authServerIssuer, redirectUri)`
* in the cache file and re-uses the existing client; falls back to a fresh
* DCR call when nothing is cached.
*/
export async function getOrRegisterClient(View on GitHub (pinned to 5be4028344)
Solutions
- Inspect the embedded status and body text in the message to see the server's reason.
- Confirm registration_endpoint is correct and reachable.
- Verify redirectUri is permitted by the provider.
- If DCR is unsupported, pre-register a client and seed the cache (see getOrRegisterClient).
Defensive patterns
Strategy: try-catch
Try / catch
try {
await registerClient(registrationEndpoint, redirectUri);
} catch (e) {
if (/dynamic client registration failed/i.test(e.message)) {
// message carries HTTP status + up to 500 chars of body
logOAuthDetail(e.message);
// for providers that reject DCR, fall back to a pre-registered client
}
throw e;
} Prevention
- Confirm the provider actually supports DCR before relying on it.
- Pre-seed a client in the cache for providers that do not.
- Make sure redirectUri is on the provider's allowlist.
When it happens
Trigger: Auth server rejected DCR with 400, 401, or 403; registration_endpoint is wrong or unreachable; server returned 5xx; rate limited with 429.
Common situations: An MCP provider does not actually support DCR despite advertising an endpoint; a corporate proxy returns 4xx; the redirectUri is not allowlisted.
Related errors
- dynamic client registration response missing client_id
- auth server ${authServer.issuer} does not advertise a regist
- token endpoint rejected request: HTTP ${res.status} ${res.st
- could not discover OAuth metadata for ${issuer}
- Could not fetch ${url} — the site may block server-side requ
AI-assisted analysis of nexu-io/open-design@5be4028344 (2026-08-12).
Data as JSON: /api/errors/0cf6e062075c89a5.
Report an issue: GitHub.