vercel/ai · error · CodeModeProtocolError
CODE_MODE_PROTOCOL_ERROR
CODE_MODE_PROTOCOL_ERROR
Error message
Code mode approval response is malformed.
What it means
This CodeModeProtocolError is thrown by assertCodeModeApprovalResponse when the value passed as an approval response fails structural validation. A valid response must be a non-null, non-array object with a string `approvalId`, a boolean `approved`, and an optional string `reason`. The library throws this to enforce the code-mode approval protocol contract, since an unexpected shape would silently corrupt the approval workflow.
Source
Thrown at packages/code-mode/src/approval.ts:31
payload: CodeModeInterruptPayload,
): payload is CodeModeApprovalInterruptPayload {
return payload.kind === CODE_MODE_TOOL_APPROVAL_KIND;
}
export function assertCodeModeApprovalResponse(
value: unknown,
): asserts value is CodeModeApprovalResponse {
if (
typeof value !== 'object' ||
value === null ||
Array.isArray(value) ||
typeof (value as { approvalId?: unknown }).approvalId !== 'string' ||
typeof (value as { approved?: unknown }).approved !== 'boolean' ||
('reason' in value &&
(value as { reason?: unknown }).reason !== undefined &&
typeof (value as { reason?: unknown }).reason !== 'string')
) {
throw new CodeModeProtocolError(
'Code mode approval response is malformed.',
);
}
}
export function normalizeApprovalResolution(
resolution: unknown,
): CodeModeApprovalResolution {
if (
typeof resolution !== 'object' ||
resolution === null ||
Array.isArray(resolution) ||
typeof (resolution as { approved?: unknown }).approved !== 'boolean' ||
('reason' in resolution &&
(resolution as { reason?: unknown }).reason !== undefined &&
typeof (resolution as { reason?: unknown }).reason !== 'string')
) {
throw new CodeModeProtocolError(View on GitHub (pinned to 69428b1f8b)
Solutions
- Log the offending value and verify it has string `approvalId`, boolean `approved`, and optional string `reason`
- Ensure you build the response from the interrupt payload's actual `approvalId` rather than a hardcoded/renamed field
- Check that the value is not null, undefined, or an array before calling continueCodeModeApproval
- Validate the response shape (e.g. with a schema or type guard) before passing it in
Example fix
// before
await continueCodeModeApproval({ approvalId: payload.id, approved: 'yes' });
// after
await continueCodeModeApproval({
approvalId: payload.approvalId,
approved: true,
reason: 'user clicked allow',
}); Defensive patterns
Strategy: type-guard
Validate before calling
function isValidApprovalResponse(v: unknown): boolean {
return (
typeof v === 'object' && v !== null && !Array.isArray(v) &&
typeof (v as any).approvalId === 'string' &&
typeof (v as any).approved === 'boolean' &&
(!('reason' in v) || (v as any).reason === undefined || typeof (v as any).reason === 'string')
);
}
if (!isValidApprovalResponse(response)) throw new Error('invalid approval response'); Type guard
function isCodeModeApprovalResponse(v: unknown): v is CodeModeApprovalResponse {
return (
typeof v === 'object' && v !== null && !Array.isArray(v) &&
typeof (v as { approvalId?: unknown }).approvalId === 'string' &&
typeof (v as { approved?: unknown }).approved === 'boolean' &&
(!('reason' in v) || (v as { reason?: unknown }).reason === undefined || typeof (v as { reason?: unknown }).reason === 'string')
);
} Try / catch
import { CodeModeProtocolError } from '.../errors.js';
try {
await continueCodeModeApproval(response);
} catch (error) {
if (CodeModeProtocolError.isInstance(error)) {
console.error('Malformed approval response:', response);
return; // reject or re-prompt the user
}
throw error;
} Prevention
- Always construct the response from the interrupt payload's approvalId field
- Never forward deserialized values without checking shape
- Add a schema/unit test for your approval-response builder
- Coerce UI inputs to booleans/strings explicitly before assembling the response
When it happens
Trigger: Passing a malformed object to continueCodeModeApproval: missing `approvalId`, wrong type (e.g. numeric id), missing or non-boolean `approved`, `reason` present but not a string, passing null/undefined, or passing an array. Also occurs when forwarding a deserialized/persisted response (e.g. from JSON in a queue or DB) whose shape changed between serialization points.
Common situations: Manually constructing a response object in a custom UI approval handler; storing approval responses in a database and reading back old/renamed field names; deserializing responses over HTTP where types were coerced (approved: "true"); upgrading SDK versions where the response schema gained/renamed fields.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- CODE_MODE_PROTOCOL_ERROR
- Continuation contains a non-JSON-serializable value.
- Code mode interrupt payload must be an object.
- Code mode interrupt payload must include a string kind.
- CODE_MODE_PROTOCOL_ERROR
AI-assisted analysis of vercel/ai@69428b1f8b (2026-08-30).
Data as JSON: /api/errors/374a5df4ae928722.
Report an issue: GitHub.