Error Codes

Every ChatSdkError carries a typed code, userMessage, developerHint, severity, retryability flag, and a docsUrl linking to this page. Catch errors by checking instanceof ChatSdkError and branching on error.code.

import { ChatSdkError } from 'gecx-chat';

try {
  await session.send('Hello');
} catch (err) {
  if (err instanceof ChatSdkError) {
    console.log(err.code, err.userMessage, err.developerHint);
    if (err.retryable) scheduleRetry();
  }
}

Categories

For category-level recovery patterns (auth retry loops, transport reconnect strategies, upload backoff, etc.) see the Error Recovery guide.


Authentication

CodeSeverityRetryableDescriptionFix
AUTH_REQUIREDhighNoNo auth provider was supplied.Pass tokenEndpointAuth(), customAuth(), or googleTokenBrokerAuth() to createChatClient.
AUTH_EXPIREDhighYesAuth token past its expiresAt. SDK will attempt auto-refresh.If recurring, lengthen token TTL or shorten prefetchBufferMs. Ensure Cache-Control: no-store on the token endpoint.
AUTH_FAILEDhighNoServer rejected auth credentials.Verify the token endpoint returns a valid token field. Check broker URL for googleTokenBrokerAuth.
TOKEN_ENDPOINT_FAILEDhighYesToken endpoint request failed (network or non-2xx).Verify endpoint reachability and CORS. Run npx gecx doctor --token-endpoint <url>.
TOKEN_ENDPOINT_INVALID_RESPONSEhighNoToken endpoint returned unparseable response.Return JSON as { "token": "...", "expiresAt": <ms>, "tokenType": "Bearer" }.

Configuration

CodeSeverityRetryableDescriptionFix
CONFIG_INVALIDmediumNoRequired config fields missing or malformed.Run client.validateConfig() and inspect errors. See schemas/config.schema.json.

Transport

CodeSeverityRetryableDescriptionFix
TRANSPORT_UNAVAILABLEmediumNoNo transport could be initialized.Pass a valid ChatTransport to createChatClient.
TRANSPORT_CONNECT_FAILEDmediumYesTransport connection failed.Check endpoint reachability, CORS, CSP connect-src. SDK retries with backoff.
STREAM_INTERRUPTEDmediumYesEvent stream closed unexpectedly.Set X-Accel-Buffering: no on proxies. SDK reconnects automatically.
STREAM_PARSE_ERRORmediumNoFailed to parse an SSE event.Ensure upstream emits valid data: { ... } frames matching TransportEvent.

Session

CodeSeverityRetryableDescriptionFix
SESSION_EXPIREDmediumNoSession ID no longer valid on backend.Create a new session with client.createSession().
SESSION_ENDEDmediumNoSession explicitly ended.Create a new session to continue.
SESSION_INVALID_STATEmediumNoInvalid state transition attempted.Wait for status === 'ready' before calling send.
SEND_FAILEDmediumYesSend request failed before response stream began.Usually transient. SDK retries when retry.maxAttempts > 1.

Client Tools

CodeSeverityRetryableDescriptionFix
TOOL_NOT_REGISTEREDmediumNoServer invoked an unregistered tool.Register all expected tools before creating the session.
TOOL_VALIDATION_FAILEDlowNoTool input failed schema validation.Compare payload to the tool's inputSchema.
TOOL_EXECUTION_FAILEDmediumNoTool handler threw during execution.Add error handling inside the tool's execute function.
TOOL_TIMEOUTmediumNoTool handler exceeded timeoutMs.Increase timeoutMs or optimize the handler.

Server Tools

CodeSeverityRetryableDescriptionFix
SERVER_TOOL_NOT_CONFIGUREDhighNoServer tool endpoint missing or proxy returned PROXY_NOT_CONFIGURED.Set http.endpoint on defineServerTool and configure the proxy.
SERVER_TOOL_HTTP_FAILEDmediumYesHTTP call to tool endpoint failed.Check proxy audit log. Confirm endpoint is reachable.
SERVER_TOOL_INVALID_RESPONSEmediumNoTool endpoint returned unparseable response.Return ServerToolResultEnvelope: { "status": "completed", "output": {...} } with Content-Type: application/json.
SERVER_TOOL_UNAUTHORIZEDhighNoProxy/backend rejected the request with 401/403.Refresh the chat token. Verify origin is in ALLOWED_ORIGINS.

Files

CodeSeverityRetryableDescriptionFix
FILE_VALIDATION_FAILEDlowNoFile failed pre-upload validation (size, type, or count).Adjust allowedFileTypes, maxFileSize, or maxFileCount.
UPLOAD_FAILEDmediumYesUpload request failed or the transport is unsupported.Use mock/proxy upload, configure uploadEndpoint, or wait for a validated inline blob contract on live session transports.
URL_NOT_ALLOWEDlowNoURL failed the allowlist check.Add the trusted host to urlAllowlist in rich content registry options.

A2UI (Agent-to-UI)

CodeSeverityRetryableDescriptionFix
A2UI_FRAME_INVALIDmediumNoMalformed A2UI frame received.Validate frame uses v0.9 and a single valid operation.
A2UI_VERSION_UNSUPPORTEDhighNoAgent sent A2UI for an unsupported protocol version.Emit version: 'v0.9' from the agent.
A2UI_CATALOG_REJECTEDmediumNoAgent referenced an unregistered catalog.Register the catalog with createA2UIRenderer.
A2UI_ACTION_INVALIDmediumNoA2UI action envelope missing required fields.Ensure action includes a string name and is dispatched from an initialized surface.
A2UI_ACTION_REJECTEDlowNoA2UI action policy blocked the action.Check action against the host policy. Use confirm instead of block when appropriate.
A2UI_RENDER_FAILEDmediumYesReact A2UI renderer threw during render.Inspect catalog, component payload, and renderer error boundary.

Network and Recovery

CodeSeverityRetryableDescriptionFix
NETWORK_OFFLINElowYesnavigator.onLine === false.In auto mode, sends queue in the outbox. In strict mode, surface the error to the user.
RECONNECT_EXHAUSTEDhighNoMax reconnect attempts reached.Increase recovery.maxAttempts or recovery.maxBackoffMs.
RESUME_NOT_SUPPORTEDmediumNoResume mode requested but transport does not support it.Downgrade recovery.resumeMode to 'replay' or use a transport with capabilities.resume: true.
LEADER_LOSTlowNoMulti-tab leader lock released unexpectedly.Usually self-heals. A follower is promoted automatically.
OUTBOX_DROPPEDmediumNoPending offline sends lost on shutdown.Persist the outbox or drain before shutdown.
IDEMPOTENCY_KEY_REJECTEDmediumYesUpstream rejected the idempotency key.Generate a fresh key with generateIdempotencyKey().

Identity

CodeSeverityRetryableDescriptionFix
IDENTITY_REQUIREDmediumNoupgradeToAuthenticated() called without externalId.Pass a non-empty externalId.
IDENTITY_CONFLICTlowYesAnother tab wrote a different identity.Informational. Centralize identity in a single host UI.
CONVERSATION_NOT_FOUNDmediumNoresumeSession called with unknown conversation ID.Call client.conversations.importRemote() first for cross-device resume.

Governance

CodeSeverityRetryableDescriptionFix
GOVERNANCE_SESSION_ERASEDmediumNoSend attempted on a deleted session.Create a new session with client.createSession().
GOVERNANCE_CONSENT_WITHDRAWNmediumNoConsent is withdrawn and policy is clear_and_block.Call governance.updateConsent() to restore consent, or change policy to clear_only.
GOVERNANCE_DELETE_FAILEDmediumYesBackend delete/forget failed.Verify proxy routes. Set requireServerAck.delete = false for local-only erasure.
GOVERNANCE_EXPORT_FAILEDmediumYesBackend export failed.Set policy.export.localFallback = true or implement the export endpoint on the proxy.
GOVERNANCE_NOT_SUPPORTEDmediumNoTransport missing required governance verb.Add the verb to the transport or relax requireServerAck.

Rich Content

CodeSeverityRetryableDescriptionFix
RICH_CONTENT_VERSION_UNSUPPORTEDlowNoServer sent a rich part version this client does not render.Register a renderer for the new version on the RichContentRegistry.
RICH_CONTENT_FAMILY_UNREGISTEREDlowNoServer sent a rich part family not in the registry.Register the family: registry.register({ family: '...', versions: [1] }).

Voice

CodeSeverityRetryableDescriptionFix
VOICE_CONSENT_REQUIREDmediumNoAudio retention requested without voice_recording consent.Grant voice_recording via the governance policy, or open the VoiceSession with retention disabled (the default).
VOICE_RECORDING_DENIEDlowNoUser declined the voice recording consent prompt.Continue without retention (transcripts only). Do not re-prompt within the same session.
VOICE_PROVIDER_UNAVAILABLEhighYesThe configured VoiceProvider failed to open a session.For Gemini Live, verify /chat/voice-token is wired and reachable. For the WebRTC stub, implement an OpenAI Realtime or LiveKit-partner adapter.
VOICE_DEVICE_PERMISSION_DENIEDmediumNoBrowser rejected getUserMedia({ audio: true }).Serve over HTTPS, check Permissions-Policy: microphone=*, and prompt the user to allow microphone access.
VOICE_DEVICE_UNAVAILABLEmediumNoNo audio input devices found, or device removed mid-session.Prompt the user to connect a microphone. On mobile Safari, ensure the tab is foregrounded.
VOICE_NEGOTIATION_FAILEDhighYesWebRTC SDP exchange failed or audio MIME negotiation rejected the offered formats.Confirm the provider supports audio/pcm;rate=16000 input and audio/pcm;rate=24000 output. Verify TURN reachability on enterprise networks.
VOICE_BARGE_IN_TIMEOUTlowYesBarge-in abort did not propagate within 1s.Check the provider stream loop and network path. Telemetry-only; the SDK still cancels the turn locally.
VOICE_TOKEN_INVALIDhighYesEphemeral voice token was rejected by the provider.Verify /chat/voice-token mints tokens with the correct model + voice scopes and that clock skew is within tolerance.
VOICE_TOKEN_ENDPOINT_MISSINGhighNovoice is configured for the bundled Gemini Live provider but no tokenEndpoint was supplied in production/staging.Add voice.tokenEndpoint pointing to your proxy /chat/voice-token route, or use voice: 'auto' to fall back to the documented default.

Memory

CodeSeverityRetryableDescriptionFix
MEMORY_ADAPTER_UNAVAILABLElowYesThe configured MemoryAdapter rejected a request — the remote backend may be down or unreachable. Sends still proceed; only the memory layer is degraded.Check adapter connectivity and credentials. The hybrid adapter will keep serving reads from the cache until the remote recovers.
MEMORY_CONSENT_WITHDRAWNlowNoA memory operation was attempted while governance consent is withdrawn or useMemory().setEnabled(false) was set.Re-enable memory via the user-controllable kill switch (useMemory().setEnabled(true)) or restore governance consent. Existing entries are preserved on disk for the duration governed by retention policy.
MEMORY_QUOTA_EXCEEDEDlowNoThe per-scope or total-bytes quota in MemoryConfig.quota was reached.Raise the quota, prune old entries with memory.delete() / clear(), or rely on retention TTLs to clean up automatically.
MEMORY_SYNC_FAILEDlowYesThe hybrid adapter could not reconcile a local optimistic write against the remote source-of-truth.Inspect the remote endpoint logs. The local cache was rolled back per HybridMemoryAdapterOptions.onRemoteFailure.
MEMORY_EXTRACTION_FAILEDlowYesThe configured MemoryExtractor threw or returned invalid output.The send already completed — this is a soft failure that drops the extraction for one turn. Check extractor configuration and the upstream model output.
MEMORY_INVALID_SCOPEmediumNoA memory operation referenced a scope that does not match the active identity, or omitted required scope fields.Verify the IdentityManager is hydrated and that the operation includes a valid identityId.
MEMORY_ENTRY_NOT_FOUNDlowNomemory.update / memory.delete was invoked with an id that does not exist in the adapter.Refresh the list with useMemory() and retry. The entry may have already been deleted or expired via retention.

Device permissions: VOICE_DEVICE_PERMISSION_DENIED and VOICE_RECORDING_DENIED predate the first-party permissions module. Cross-platform code should branch on PERMISSION_* codes thrown by PermissionManager.ensure() — see the Permissions section below.

Permissions

Cross-platform device-permission errors raised by PermissionManager.ensure() and UploadManager.attachFromCamera/Microphone/Screen. The data-only request() form never throws — it resolves with { status, reason } instead. The throwing surface here is the convenience used by higher-level call sites (VoiceSession.beginInput, attachFromCamera).

CodeSeverityRetryableDescriptionFix
PERMISSION_DENIEDmediumNoUser dismissed or rejected the OS / browser permission prompt.Inspect details.capability and details.reason. Surface rationale UI and let the user opt back in deliberately — do not re-prompt automatically.
PERMISSION_BLOCKEDmediumNoPlatform reports the capability is permanently blocked (native: app-level denial).Render an "open settings" recovery path. On web there is no programmatic deep link — show instructions. Browsers cannot reliably distinguish blocked from per-session denial.
PERMISSION_UNSUPPORTEDmediumNoThe configured PermissionProvider reports the capability is unavailable.Common causes: SSR, non-DOM web worker, missing platform plugin (RN/Capacitor), or navigator.mediaDevices is undefined. Insecure context is signalled separately as PERMISSION_INSECURE_CONTEXT.
PERMISSION_INSECURE_CONTEXTmediumNoBrowser refused to expose getUserMedia / getDisplayMedia / geolocation because window.isSecureContext is false.Serve the page over HTTPS or use localhost during development. The SDK surfaces this distinct from PERMISSION_UNSUPPORTED so the host can render a setup-guidance message.
PERMISSION_TIMEOUTlowYesUser did not resolve the prompt within the host-supplied timeout, or geolocation hit its own timeout.Offer a retry affordance — most users grant on a second try after re-reading rationale copy.
PERMISSION_HARDWARE_UNAVAILABLEmediumYesPlatform returned NotFoundError / NotReadableError / OverconstrainedError, or geolocation reported POSITION_UNAVAILABLE.The capability is supported but the underlying device is missing, busy, or rejected the constraints. Prompt the user to plug in / unplug peripherals; relax constraints (resolution, facingMode) before failing hard.

Computer-use

The computer_use server tool is default off for security. Errors below surface either before any vendor session is allocated (fail-fast SDK guard) or while a live session is mid-flight (proxy-enforced). Every transition is also recorded as a governance.computer_use.* audit event.

CodeSeverityRetryableDescriptionFix
COMPUTER_USE_NOT_ENABLEDmediumNogovernance.computerUse.enabled is false (the default) or the proxy is missing COMPUTER_USE_PROVIDER.Set governance.computerUse to a populated policy (enabled: true, allowlist: [...]) and configure the proxy provider env vars.
COMPUTER_USE_ALLOWLIST_VIOLATIONhighNoA requested URL was not in governance.computerUse.allowlist.Never widen the SDK-side allowlist to suppress this; fix the upstream agent prompt or extend the policy intentionally after a security review.
COMPUTER_USE_DURATION_EXCEEDEDmediumNoSession exceeded maxDurationMs (default 5 minutes).Raise the cap deliberately or have the agent break the goal into smaller actions.
COMPUTER_USE_ACTION_LIMIT_EXCEEDEDmediumNoSession exceeded maxActionsPerSession (default 30).Inspect the governance.computer_use.action audit events for a loop pattern; tighten the agent's plan or raise the cap deliberately.
COMPUTER_USE_USER_ABORTlowNoThe user clicked Abort on the <ComputerUseSurface>.This is not an error — surface it as a normal cancellation in product UX.
COMPUTER_USE_PROVIDER_UNAVAILABLEhighYesThe provider (Browserbase or Mock) failed to open a session, or the kill-switch is engaged.For Browserbase, check BROWSERBASE_API_KEY / BROWSERBASE_PROJECT_ID and the vendor status page. For the kill-switch, flip COMPUTER_USE_KILL_SWITCH or governance.triggerComputerUseKill(false) once safe.

Agent graph

CodeSeverityRetryableDescriptionFix
A2A_TRANSPORT_ERRORmediumYesThe A2A JSON-RPC call to a specialist agent failed (network error, non-2xx, unparseable body, or SSE error frame).Check the specialist endpoint, AgentCard URL, and any auth headers. The router falls back to its declared fallback when the in-flight call fails.
A2A_AGENT_UNAVAILABLEmediumYesThe A2A endpoint returned a 5xx or failed-state task.The router will surface the configured fallback for this turn; if no fallback is configured, the turn errors with this code. Restore the specialist or escalate via routeTo: 'human'.
A2A_TIMEOUTmediumYesThe A2A request exceeded the configured per-specialist timeoutMs (default 8s).Increase A2AAgentClientOptions.timeoutMs for the specialist or examine the specialist for slow handlers.
A2A_AGENT_CARD_INVALIDhighNoThe AgentCard fetched from the specialist did not match the expected A2A schema, or used an unsupported protocolVersion.Verify the .well-known/agent.json document is valid JSON with name, protocolVersion, and url. The SDK supports A2A 0.x.
AGENT_GRAPH_INVALIDhighNoagentGraph() rejected the supplied definition (duplicate node ids, missing entry node, or a router rule whose routeTo does not resolve).Inspect the error details.cause and fix the configuration before constructing the chat client.
AGENT_GRAPH_NODE_NOT_FOUNDhighNoA router decision targeted a node id that is not registered in the graph.Typically a typo in a routeTo string. The error includes details.knownNodes listing the valid ids.
AGENT_GRAPH_MAX_DEPTHhighNoA turn caused the router to recurse beyond AgentGraphConfig.maxDepth (default 3). Usually a routing loop where two routers hand off to each other.Add a base-case rule that breaks the loop, or raise maxDepth if your graph is genuinely deeper than three router hops.

Analytics

CodeSeverityRetryableDescriptionFix
ANALYTICS_SINK_FAILEDlowYesA ProductAnalyticsSink threw or its promise rejected. The collector swallows sink errors by default — this code only surfaces when you wrap a sink with strict error propagation.Inspect the sink's stack trace. Sinks must never break the SDK, so consider wrapping with try/catch and rate-limiting any logging to avoid noisy retries.
ANALYTICS_AGGREGATION_INVALID_WINDOWmediumNocomputeDeflectionRate / computeCsat / etc. received an invalid TimeRangeFilter: both range and window set, a zero-length window, or a negative duration.Pass exactly one of range (preset like '7d') or window (explicit { startMs, endMs }). The window must be half-open with endMs > startMs.

Commerce

CodeSeverityRetryableDescriptionFix
COMMERCE_PII_LEAKcriticalNocommerceGovernance({ strict: true }) detected an unredacted PAN or PII pattern in a tool input, rich-content part, transcript, or debug bundle at the session-state-entry boundary.Apply redactCommercePii() or redactCommercePiiDeep() at the boundary before persisting, emitting analytics, or surfacing in approval text. See commerce.md.

Agentis Platform

CodeSeverityRetryableDescriptionFix
AGENTIS_SESSION_INIT_FAILEDhighYesThe customer session route could not complete Agentis :initializeSession, or the response was malformed.Keep :initializeSession server-side through createAgentisSessionHandler, confirm OAuth impersonation, and check route logs. See agentis-integration.md.
AGENTIS_TENANT_NOT_ALLOWLISTEDhighNoAgentis returned 404 despite valid credentials. The numeric GCP project is not allowlisted in TenantManager.Ask your Google FDE to apply the COMMERCE_PARTNER label. Verify agenticapplications.googleapis.com, AGENTIS_AGENT_ID, and AGENTIS_CLIENT_ID.
AGENTIS_AUTH_PRINCIPAL_REJECTEDhighNoAgentis rejected the OAuth principal with 401/403.Confirm the server-side token broker uses service-account impersonation with the cloud-platform scope. API keys and end-user OAuth tokens cannot initialize Agentis sessions.
AGENTIS_RECAPTCHA_REQUIREDmediumYesThe server-side reCAPTCHA hook required or rejected verification.Pass the customer route's expected reCAPTCHA token and verify it server-side before session allocation.
AGENTIS_SHOPPING_EVENT_FAILEDlowYesThe customer shopping-event relay could not deliver :createShoppingEvent.Verify AGENTIS_PROJECT_NUMBER, OAuth impersonation, relay CORS, and the { parent, shoppingEvent } envelope.

Voice (additional)

CodeSeverityRetryableDescriptionFix
VOICE_TOKEN_ENDPOINT_MISSINGhighNoAn explicit geminiLive voice provider was configured without a tokenEndpoint. Surfaced by validateConfig() in production/staging.Pass tokenEndpoint: '/api/chat/voice-token' (or your proxy's path) to createGeminiLiveProvider. The proxy reference implements this route.

Internal

CodeSeverityRetryableDescriptionFix
INTERNAL_ERRORcriticalNoUnexpected SDK bug.Capture a debug bundle and file an issue with requestId and correlationId.
Source: docs/reference/error-codes.md