{"record":{"id":"e701eac5beed029d","repo":"paperclipai/paperclip","slug":"native-session-attach-binding-mismatch","errorCode":"native_session_attach_binding_mismatch","errorMessage":"native_session_attach_binding_mismatch","messagePattern":"native_session_attach_binding_mismatch","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/paperclip-runner/src/backends/harness-driver-backend.ts","lineNumber":476,"sourceCode":"        this.#session.resolveRuntimeRequest !== undefined,\n      runtimeRequestHandoff: this.#session.handoffRuntimeRequest !== undefined,\n      goals: this.#session.goal !== undefined,\n      threadLineage: this.#session.lineage !== undefined,\n    };\n  }\n\n  async attachRun(input: {\n    identity: OpenNativeSessionInput[\"identity\"];\n  }): Promise<void> {\n    this.#assertProtocolIntegrity();\n    const currentIdentity = this.#input.identity;\n    if (\n      input.identity.sessionId !== currentIdentity.sessionId ||\n      input.identity.companyId !== currentIdentity.companyId ||\n      input.identity.issueId !== currentIdentity.issueId ||\n      input.identity.agentId !== currentIdentity.agentId\n    ) {\n      throw new Error(\"native_session_attach_binding_mismatch\");\n    }\n    if (this.#session.attachRun === undefined) {\n      throw new Error(\"native_session_multi_run_unavailable\");\n    }\n    try {\n      await this.#session.attachRun({ runId: input.identity.runId });\n      this.#assertProtocolIntegrity();\n    } catch (error) {\n      this.#rethrowProtocolIntegrity(error);\n      throw error;\n    }\n    this.#input = { ...this.#input, identity: structuredClone(input.identity) };\n    this.#terminal = null;\n    this.#explicitlyCancelled = false;\n  }\n\n  async detachControllerForRestart(): Promise<void> {\n    if (this.#session.detachControllerForRestart === undefined) return;","sourceCodeStart":458,"sourceCodeEnd":494,"githubUrl":"https://github.com/paperclipai/paperclip/blob/01ad8584922b5d85292b1723cae71fa0d9b07a19/packages/paperclip-runner/src/backends/harness-driver-backend.ts#L458-L494","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nawait backend.attachRun({ identity: { sessionId, companyId: otherCompanyId, issueId, agentId, runId } });\n// after\nif (currentIdentity.companyId !== companyId) {\n  await backend.close();\n  backend = await createSession({ sessionId, companyId, issueId, agentId });\n}\nawait backend.attachRun({ identity: { sessionId, companyId, issueId, agentId, runId } });","handlingStrategy":"validation","validationCode":"const mismatches = ['sessionId','companyId','issueId','agentId'].filter(k => input.identity[k] !== currentIdentity[k]);\nif (mismatches.length > 0) throw new Error(`identity mismatch: ${mismatches.join(',')}`);","typeGuard":"function isSameIdentity(a, b) {\n  return a.sessionId === b.sessionId && a.companyId === b.companyId && a.issueId === b.issueId && a.agentId === b.agentId;\n}","tryCatchPattern":"try { await backend.attachRun({ identity }); } catch (e) { if (e.message === 'native_session_attach_binding_mismatch') { await recreateSessionForIdentity(identity); } else throw e; }","preventionTips":["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"],"tags":["session","identity-mismatch","harness"],"backgroundTag":"invalid-state-transition","analyzedSha":"01ad8584922b5d85292b1723cae71fa0d9b07a19","analyzedAt":"2026-09-10T03:14:50.855Z","contentChangedAt":"2026-09-10T03:14:50.855Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}