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

  1. Verify the ACP session initialization (session/new) completed successfully and store the returned session id into handle.backendSessionId before opening ports.
  2. Validate the handle before use: assert handle.backendSessionId is a non-empty trimmed string.
  3. If the runtime restarted, re-run session initialization to obtain a new backendSessionId rather than reusing the stale handle.
  4. 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

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


AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10). Data as JSON: /api/errors/2537f50eed0ca50f. Report an issue: GitHub.