paperclipai/paperclip · error
native_session_attach_binding_mismatch
native_session_attach_binding_mismatch
Error message
native_session_attach_binding_mismatch
What it means
attachRun verifies that the run identity being attached (sessionId, companyId, issueId, agentId) exactly matches the identity the native session was originally created with. If any of the four fields differ, the backend refuses to attach the run to a session bound to different coordinates and throws this error. It is a safety guard against cross-issue or cross-agent session reuse in the harness driver backend.
Source
Thrown at packages/paperclip-runner/src/backends/harness-driver-backend.ts:476
this.#session.resolveRuntimeRequest !== undefined,
runtimeRequestHandoff: this.#session.handoffRuntimeRequest !== undefined,
goals: this.#session.goal !== undefined,
threadLineage: this.#session.lineage !== undefined,
};
}
async attachRun(input: {
identity: OpenNativeSessionInput["identity"];
}): Promise<void> {
this.#assertProtocolIntegrity();
const currentIdentity = this.#input.identity;
if (
input.identity.sessionId !== currentIdentity.sessionId ||
input.identity.companyId !== currentIdentity.companyId ||
input.identity.issueId !== currentIdentity.issueId ||
input.identity.agentId !== currentIdentity.agentId
) {
throw new Error("native_session_attach_binding_mismatch");
}
if (this.#session.attachRun === undefined) {
throw new Error("native_session_multi_run_unavailable");
}
try {
await this.#session.attachRun({ runId: input.identity.runId });
this.#assertProtocolIntegrity();
} catch (error) {
this.#rethrowProtocolIntegrity(error);
throw error;
}
this.#input = { ...this.#input, identity: structuredClone(input.identity) };
this.#terminal = null;
this.#explicitlyCancelled = false;
}
async detachControllerForRestart(): Promise<void> {
if (this.#session.detachControllerForRestart === undefined) return;View on GitHub (pinned to 01ad858492)
Solutions
- Log both input.identity and the session's currentIdentity and align the mismatched field before calling attachRun
- Create a fresh native session for the new identity instead of attaching to the existing one
- Ensure the caller derives identity from the same record that bootstrapped the session (single source of truth)
- If the identity legitimately changed, detach/tear down the old session and re-initialize with the new binding
Example fix
// before
await backend.attachRun({ identity: { sessionId, companyId: otherCompanyId, issueId, agentId, runId } });
// after
if (currentIdentity.companyId !== companyId) {
await backend.close();
backend = await createSession({ sessionId, companyId, issueId, agentId });
}
await backend.attachRun({ identity: { sessionId, companyId, issueId, agentId, runId } }); Defensive patterns
Strategy: validation
Validate before calling
const mismatches = ['sessionId','companyId','issueId','agentId'].filter(k => input.identity[k] !== currentIdentity[k]);
if (mismatches.length > 0) throw new Error(`identity mismatch: ${mismatches.join(',')}`); Type guard
function isSameIdentity(a, b) {
return a.sessionId === b.sessionId && a.companyId === b.companyId && a.issueId === b.issueId && a.agentId === b.agentId;
} Try / catch
try { await backend.attachRun({ identity }); } catch (e) { if (e.message === 'native_session_attach_binding_mismatch') { await recreateSessionForIdentity(identity); } else throw e; } Prevention
- Derive attach identity from the same record that created the session
- Log both identities on mismatch to speed diagnosis
- Avoid caching native sessions across issues or companies
When it happens
Trigger: Calling attachRun with input.identity whose sessionId, companyId, issueId, or agentId does not equal the currentIdentity captured when the native session was started. Typical: reusing a cached session object for a different issue, or a stale session after an issue was re-keyed/re-created.
Common situations: Recovering from a crash by reattaching to a persisted sessionId but with a new issueId; passing the wrong issue's runId to a long-lived session; company/agent rebinding after an admin reassignment; a bug where identity is rebuilt from a different source than the session bootstrap.
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
- Anthropic pinned Agent version identity does not match the s
- native_session_multi_run_unavailable
- steering is unavailable
- native_session_goal_unavailable
- OpenCode recovery failed
AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10).
Data as JSON: /api/errors/e701eac5beed029d.
Report an issue: GitHub.