paperclipai/paperclip · warning
Chat SDK runtime is shutting down
Error message
Chat SDK runtime is shutting down
What it means
assertReplacementCurrent is the guard applied when installing a replacement chat SDK runtime for an endpoint. If the runtime is shutting down, it throws 'Chat SDK runtime is shutting down'; if the recorded replacement generation for the endpoint no longer matches, it throws the 'was superseded' error. This ensures only the newest replacement wins and none are installed during teardown.
Source
Thrown at server/src/services/chat-sdk-runtime.ts:3183
if (!previous) return false;
this.endpoints.delete(endpointId);
this.retiringEndpoints.set(endpointId, previous);
await previous.shutdown();
this.retiringEndpoints.delete(endpointId);
return true;
}
private nextReplacementGeneration(endpointId: string): number {
const next = (this.replacementGenerations.get(endpointId) ?? 0) + 1;
this.replacementGenerations.set(endpointId, next);
return next;
}
private assertReplacementCurrent(
endpointId: string,
generation: number,
): void {
if (this.shuttingDown) throw new Error("Chat SDK runtime is shutting down");
if (this.replacementGenerations.get(endpointId) !== generation) {
throw new Error(
`Chat SDK runtime replacement for endpoint ${endpointId} was superseded`,
);
}
}
async replaceEndpoint(
options: CreateChatSdkEndpointRuntimeOptions,
): Promise<ChatSdkEndpointRuntime> {
if (this.shuttingDown) throw new Error("Chat SDK runtime is shutting down");
const generation = this.nextReplacementGeneration(options.endpointId);
return await this.enqueueLifecycle(options.endpointId, async () => {
this.assertReplacementCurrent(options.endpointId, generation);
await this.retireEndpoint(options.endpointId);
this.assertReplacementCurrent(options.endpointId, generation);
const next = createChatSdkEndpointRuntime(options);
this.endpoints.set(options.endpointId, next);View on GitHub (pinned to 01ad858492)
Solutions
- Check runtime shutdown state before scheduling a replacement; skip replacements during teardown
- Re-read the latest generation for the endpoint and re-issue the replacement if superseded
- Serialize replacement installation per endpoint (queue or lock) to avoid generation races
- Treat the error as a benign no-op when it occurs during shutdown and let the new runtime take over
Example fix
// before
runtime.installReplacement(endpointId, generation);
// after
const latest = runtime.getReplacementGeneration(endpointId);
if (latest === generation && !runtime.isShuttingDown) {
runtime.installReplacement(endpointId, generation);
} Defensive patterns
Strategy: try-catch
Validate before calling
if (runtime.isShuttingDown) return; // skip replacement during teardown
Try / catch
try { installReplacement(endpointId, generation); } catch (e) { if ((e as Error).message.startsWith('Chat SDK runtime')) { /* benign: superseded or shutting down; skip */ } else throw e; } Prevention
- Serialize per-endpoint replacement installation with a lock or queue
- Re-read the latest generation before installing and retry once if superseded
- Suppress this error as a no-op during process shutdown
- Log generation mismatches to detect racing restart routines
When it happens
Trigger: Installing a runtime replacement concurrently with runtime shutdown, or a replacement whose generation counter no longer equals the latest registered generation for that endpointId (an even newer replacement already claimed the slot).
Common situations: Service shutdown racing an in-flight endpoint swap; two restart/replacement flows racing for the same endpoint; a restart routine issuing a second generation before the first is installed.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Chat SDK endpoint runtime was retired
- ACPX provider ownership admission is already active
- ACPX runtime host is closing
- capability_live_attempt_not_running
- Capability live turn admission was abandoned during teardown
AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10).
Data as JSON: /api/errors/bd222170d08f8fa4.
Report an issue: GitHub.