paperclipai/paperclip · error
ACPX runtime omitted backendSessionId
Error message
ACPX runtime omitted backendSessionId
What it means
requireIdentity() also requires a non-empty backendSessionId on the ACP runtime handle. The backendSessionId is the real ACP protocol session id used to route traffic to the backend agent; a handle without it cannot participate in the ACP session, so the adapter throws before establishing port identity.
Source
Thrown at packages/paperclip-runner/src/drivers/acpx/codex-runtime-adapter.ts:1814
tokensUsed: optionalNumber(goal.tokensUsed),
timeUsedSeconds: optionalNumber(goal.timeUsedSeconds),
iterations: optionalNumber(goal.iterations),
lastReason:
goal.lastReason === null || typeof goal.lastReason === "string"
? goal.lastReason
: undefined,
createdAt: optionalTimestamp(goal.createdAt),
updatedAt: optionalTimestamp(goal.updatedAt),
},
};
}
function requireIdentity(handle: AcpRuntimeHandle): AcpxRuntimePortIdentity {
const acpxRecordId = nonEmptyRuntimeIdentity(handle.acpxRecordId);
if (!acpxRecordId) throw new Error("ACPX runtime omitted acpxRecordId");
const backendSessionId = nonEmptyRuntimeIdentity(handle.backendSessionId);
if (!backendSessionId) {
throw new Error("ACPX runtime omitted backendSessionId");
}
return {
acpxRecordId,
backendSessionId,
// ACPX agents do not all advertise a distinct native thread identity.
// In that case the backend ID is the real ACP protocol session, so retain
// it explicitly rather than inventing a Paperclip-owned identifier.
agentSessionId:
nonEmptyRuntimeIdentity(handle.agentSessionId) ?? backendSessionId,
};
}
function definedEnvironment(
environment: Readonly<NodeJS.ProcessEnv>,
): Record<string, string> {
return Object.fromEntries(
Object.entries(environment).filter(
(entry): entry is [string, string] => entry[1] !== undefined,View on GitHub (pinned to 01ad858492)
Solutions
- Verify the ACP session initialization (session/new) completed successfully and store the returned session id into handle.backendSessionId before opening ports.
- Validate the handle before use: assert handle.backendSessionId is a non-empty trimmed string.
- If the runtime restarted, re-run session initialization to obtain a new backendSessionId rather than reusing the stale handle.
- Check adapter/runtime version alignment if the session id arrives under a different property name.
Example fix
// before
const handle = { acpxRecordId: recordId } as AcpRuntimeHandle;
const identity = requireIdentity(handle); // throws
// after
const handle = { acpxRecordId: recordId, backendSessionId: session.id } as AcpRuntimeHandle;
const identity = requireIdentity(handle); Defensive patterns
Strategy: validation
Validate before calling
function hasBackendSessionId(h) {
return typeof h?.backendSessionId === 'string' && h.backendSessionId.trim().length > 0;
}
if (!hasBackendSessionId(handle)) throw new Error('handle missing backendSessionId before port setup'); Type guard
function hasBackendSessionId(h: AcpRuntimeHandle): h is AcpRuntimeHandle & { backendSessionId: string } {
return typeof h.backendSessionId === 'string' && h.backendSessionId.trim() !== '';
} Try / catch
try {
const identity = requireIdentity(handle);
openPorts(identity);
} catch (err) {
if (err.message === 'ACPX runtime omitted backendSessionId') {
// session handshake did not complete; re-run session/new
handle.backendSessionId = await initializeAcpSession(runtime);
} else throw err;
} Prevention
- Await the ACP session/new handshake before constructing the handle.
- Never reuse handles across runtime restarts; re-initialize to get a fresh backendSessionId.
- Keep adapter and runtime versions aligned so the session id field name matches.
When it happens
Trigger: Calling requireIdentity() (directly or via port setup) with an AcpRuntimeHandle whose backendSessionId is undefined/null/empty — e.g. the ACPX runtime never reported a session id, session initialization failed silently, or the handle was assembled from a partial event payload.
Common situations: ACP initialize/session-new handshake did not complete but downstream code proceeded; runtime crash/restart produced a fresh handle without re-initializing the session; tests or scripts fabricating handles with only acpxRecordId set; agent adapter version mismatch where session id is reported under a different field name.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- ACPX runtime omitted acpxRecordId
- ACPX sidecar runtime context must be pre-materialized
- persisted Codex ACPX session identity is inconsistent
- ACPX provider dependency ancestry is invalid
- ACPX provider runtime executable count is invalid
AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10).
Data as JSON: /api/errors/2537f50eed0ca50f.
Report an issue: GitHub.