vercel/ai · error · Error
Cartesia realtime client secret response did not include a t
Error message
Cartesia realtime client secret response did not include a token.
What it means
If the /access-token request succeeds (2xx) but the parsed JSON body does not contain a non-empty string token field, doCreateClientSecret throws. The client treats a missing/empty token as unusable — a client secret cannot be issued without it, so this indicates an unexpected success response shape.
Source
Thrown at packages/cartesia/src/cartesia-realtime-model.ts:110
...this.config.headers(),
'Content-Type': 'application/json',
},
body: JSON.stringify({
grants: { stt: true },
...(expiresIn != null ? { expires_in: expiresIn } : {}),
}),
});
if (!response.ok) {
const text = await response.text();
throw new Error(
`Cartesia realtime client secret request failed: ${response.status} ${text}`,
);
}
const data = (await response.json()) as { token?: unknown };
if (typeof data.token !== 'string' || data.token.length === 0) {
throw new Error(
'Cartesia realtime client secret response did not include a token.',
);
}
const turnDetection = sessionConfig?.turnDetection;
const useTurnDetection =
turnDetection === undefined ||
(turnDetection !== null && turnDetection.type !== 'disabled');
const inputAudioFormat = sessionConfig?.inputAudioFormat;
const url = new URL(
useTurnDetection
? `${this.config.baseURL}/stt/turns/websocket`
: `${this.config.baseURL}/stt/websocket`,
);
url.protocol = url.protocol === 'http:' ? 'ws:' : 'wss:';
url.searchParams.set('model', this.modelId);
url.searchParams.set(
'encoding',View on GitHub (pinned to 69428b1f8b)
Solutions
- Log the raw response body to see what the endpoint actually returned under a 200 status.
- Verify this.config.baseURL points to the genuine Cartesia API (https://api.cartesia.ai), not a proxy or wrong region URL.
- Check your Cartesia account/plan includes realtime access-token issuance.
- Upgrade @ai-sdk/cartesia in case the token response schema changed and the provider needs an update.
Defensive patterns
Strategy: type-guard
Validate before calling
// Validate the endpoint returns JSON with a token before trusting it:
const res = await fetch(`${baseURL}/access-token`, { method: 'POST' });
const ct = res.headers.get('content-type') ?? '';
if (!ct.includes('application/json')) console.error('Non-JSON response from /access-token — check baseURL'); Type guard
function hasToken(data: unknown): data is { token: string } {
return typeof data === 'object' && data !== null &&
'token' in data && typeof (data as { token: unknown }).token === 'string' &&
(data as { token: string }).token.length > 0;
} Try / catch
try {
return await model.doCreateClientSecret(options);
} catch (e) {
if (/did not include a token/.test(String(e.message))) {
// verify baseURL/plan, then retry once
return retry(() => model.doCreateClientSecret(options), 1);
}
throw e;
} Prevention
- Ensure baseURL is the real Cartesia API so 200 responses are genuine JSON token payloads.
- Confirm your Cartesia plan/account can issue realtime access tokens.
- Log the raw 200 body when this occurs to catch schema drift early.
When it happens
Trigger: Cartesia returns 200 with a body lacking token (schema change, HTML error page served with 200, empty body, or a body keyed differently, e.g. { secret: ... }).
Common situations: Misconfigured baseURL pointing at a non-Cartesia endpoint that returns 200 HTML; authenticated but under-privileged key returning an empty success payload; API version drift.
Related errors
- Cartesia realtime client secret request failed: ${response.s
- Google Generative AI API key is required for realtime token
- Google realtime auth token request failed: ${response.status
- Invalid argument for parameter requests: request IDs must be
- ALIBABA_VIDEO_GENERATION_ERROR
AI-assisted analysis of vercel/ai@69428b1f8b (2026-08-30).
Data as JSON: /api/errors/d528d2dc6f2d7bc7.
Report an issue: GitHub.