nexu-io/open-design · error · Error

dynamic client registration response missing client_id

Error message

dynamic client registration response missing client_id

What it means

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.

Source

Thrown at apps/daemon/src/mcp-oauth.ts:275

    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(
  dataDir: string,
  authServer: AuthorizationServerMetadata,
  redirectUri: string,
  fetchImpl: typeof fetch = fetch,
): Promise<RegisteredClient> {
  const cache = await readClientCache(dataDir);

View on GitHub (pinned to 5be4028344)

Solutions

  1. Inspect the raw DCR response body to confirm the real schema.
  2. If the provider wraps client_id, add compatibility handling or pre-register a static client.
  3. Verify you are hitting the true registration_endpoint.
Defensive patterns

Strategy: try-catch

Try / catch

try {
  await registerClient(registrationEndpoint, redirectUri);
} catch (e) {
  if (/missing client_id/i.test(e.message)) {
    // inspect the raw DCR body; provider may return a non-standard envelope
    // consider pre-registering a static client instead
  }
  throw e;
}

Prevention

When it happens

Trigger: Server returned 200 with an empty or partial body; returned JSON parsed but without client_id; the endpoint returns a different envelope schema.

Common situations: A non-RFC8252-conformant provider; an endpoint that wraps client_id inside another object.

Related errors


AI-assisted analysis of nexu-io/open-design@5be4028344 (2026-08-12). Data as JSON: /api/errors/d4a38d8c0135f0df. Report an issue: GitHub.