{"record":{"id":"d4a38d8c0135f0df","repo":"nexu-io/open-design","slug":"dynamic-client-registration-response-missing-clien","errorCode":null,"errorMessage":"dynamic client registration response missing client_id","messagePattern":"dynamic client registration response missing client_id","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/daemon/src/mcp-oauth.ts","lineNumber":275,"sourceCode":"    application_type: 'web',\n  };\n  const res = await fetchImpl(registrationEndpoint, {\n    method: 'POST',\n    headers: {\n      'content-type': 'application/json',\n      accept: 'application/json',\n    },\n    body: JSON.stringify(body),\n  });\n  if (!res.ok) {\n    const txt = await safeText(res);\n    throw new Error(\n      `dynamic client registration failed: HTTP ${res.status} ${res.statusText} ${txt}`,\n    );\n  }\n  const json = (await res.json()) as { client_id?: string; client_secret?: string };\n  if (!json.client_id) {\n    throw new Error('dynamic client registration response missing client_id');\n  }\n  const out: { clientId: string; clientSecret?: string } = { clientId: json.client_id };\n  if (json.client_secret) out.clientSecret = json.client_secret;\n  return out;\n}\n\n/**\n * Cached version of `registerClient`. Looks up `(authServerIssuer, redirectUri)`\n * in the cache file and re-uses the existing client; falls back to a fresh\n * DCR call when nothing is cached.\n */\nexport async function getOrRegisterClient(\n  dataDir: string,\n  authServer: AuthorizationServerMetadata,\n  redirectUri: string,\n  fetchImpl: typeof fetch = fetch,\n): Promise<RegisteredClient> {\n  const cache = await readClientCache(dataDir);","sourceCodeStart":257,"sourceCodeEnd":293,"githubUrl":"https://github.com/nexu-io/open-design/blob/5be4028344c2eb4c667c5a97bda8f750c5597ef7/apps/daemon/src/mcp-oauth.ts#L257-L293","documentation":"registerClient received a 2xx from the DCR endpoint but the JSON body lacks client_id, the one field DCR must return. This indicates a misbehaving or non-conformant auth server returning a partial, empty, or differently-shaped body on a success status.","triggerScenarios":"Server returned 200 with an empty or partial body; returned JSON parsed but without client_id; the endpoint returns a different envelope schema.","commonSituations":"A non-RFC8252-conformant provider; an endpoint that wraps client_id inside another object.","solutions":["Inspect the raw DCR response body to confirm the real schema.","If the provider wraps client_id, add compatibility handling or pre-register a static client.","Verify you are hitting the true registration_endpoint."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await registerClient(registrationEndpoint, redirectUri);\n} catch (e) {\n  if (/missing client_id/i.test(e.message)) {\n    // inspect the raw DCR body; provider may return a non-standard envelope\n    // consider pre-registering a static client instead\n  }\n  throw e;\n}","preventionTips":["Pre-register clients for providers known to return non-standard DCR bodies.","Smoke-test DCR against a new provider before shipping.","Confirm the endpoint URL is the true registration_endpoint."],"tags":["oauth","dcr","protocol"],"backgroundTag":null,"analyzedSha":"5be4028344c2eb4c667c5a97bda8f750c5597ef7","analyzedAt":"2026-08-12T12:03:58.812Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}