paperclipai/paperclip · error
ACPX runtime omitted acpxRecordId
Error message
ACPX runtime omitted acpxRecordId
What it means
requireIdentity() validates that an ACP runtime handle carries a non-empty acpxRecordId before the adapter will open runtime ports. The acpxRecordId is the persistent identifier of the ACPX runtime record in the control plane; without it the adapter cannot bind or verify which runtime record a session belongs to, so it throws instead of proceeding with a corrupt/anonymous handle.
Source
Thrown at packages/paperclip-runner/src/drivers/acpx/codex-runtime-adapter.ts:1811
status,
tokenBudget:
goal.tokenBudget === null ? null : optionalNumber(goal.tokenBudget),
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> {View on GitHub (pinned to 01ad858492)
Solutions
- Ensure the runtime bootstrap path persists the ACPX runtime record and copies its id into handle.acpxRecordId before opening ports.
- Validate the handle shape right after obtaining it (assert typeof handle.acpxRecordId === 'string' && handle.acpxRecordId.trim() !== '').
- Upgrade/check the ACPX runtime version so it reports acpxRecordId in its bootstrap response.
- If the handle came from persistence, confirm the record row exists and was not deleted mid-session.
Example fix
// before: handle built without the record id
const handle = { backendSessionId: session.id } as AcpRuntimeHandle;
const identity = requireIdentity(handle);
// after
const handle = { acpxRecordId: runtimeRecord.id, backendSessionId: session.id } as AcpRuntimeHandle;
const identity = requireIdentity(handle); Defensive patterns
Strategy: validation
Validate before calling
function hasAcpxRecordId(h) {
return typeof h?.acpxRecordId === 'string' && h.acpxRecordId.trim().length > 0;
}
if (!hasAcpxRecordId(handle)) throw new Error('handle missing acpxRecordId before port setup'); Type guard
function hasAcpxRecordId(h: AcpRuntimeHandle): h is AcpRuntimeHandle & { acpxRecordId: string } {
return typeof h.acpxRecordId === 'string' && h.acpxRecordId.trim() !== '';
} Try / catch
try {
const identity = requireIdentity(handle);
openPorts(identity);
} catch (err) {
if (err.message === 'ACPX runtime omitted acpxRecordId') {
// re-bootstrap the runtime record and rebuild the handle
handle = await rebuildRuntimeHandle();
} else throw err;
} Prevention
- Build handles only through the bootstrap factory that persists the runtime record and copies its id.
- Validate handle shape immediately after deserialization or JSON round-trips.
- Pin ACPX runtime versions so the record id is always present in bootstrap output.
When it happens
Trigger: Passing an AcpRuntimeHandle whose acpxRecordId is undefined, null, empty string, or whitespace-only into requireIdentity() — typically when a handle was constructed from an incomplete spawn/bootstrap result, or a deserialized handle lost the field.
Common situations: A runtime record failed to persist before the handle was created (DB write failure upstream); an older ACPX runtime version that did not return acpxRecordId; code that manually constructs a handle object and forgets the field; JSON round-trip dropping undefined fields.
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 backendSessionId
- 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/f3202a57c468cbdf.
Report an issue: GitHub.