paperclipai/paperclip · error
native_session_multi_run_unavailable
native_session_multi_run_unavailable
Error message
native_session_multi_run_unavailable
What it means
Thrown as a bare Error (code `native_session_multi_run_unavailable`) when a native session is being resumed via `options.existingSession` but that session object lacks an `attachRun` function. The runtime requires an attachRun capability to re-bind a retained provider session to a new run; without it, multi-run attachment of that session is unsupported and resume cannot proceed.
Solutions
- Recreate the session instead of resuming: drop existingSession and start a fresh native session run
- Ensure the code path producing the persisted session supplies attachRun (upgrade the adapter/runtime that created it)
- Verify the provider actually supports multi-run attachment before attempting to attach a retained sessionId
- Check for version mismatch between where the session was persisted and the current runner version
Example fix
// before
await startNativeSession({ existingSession: persistedSession }); // attachRun undefined
// after
if (typeof persistedSession.attachRun !== "function") {
await startNativeSession({}); // fresh session
} else {
await startNativeSession({ existingSession: persistedSession });
} Defensive patterns
Strategy: type-guard
Validate before calling
if (options.existingSession && typeof options.existingSession.attachRun !== "function") {
throw new Error("Retained session lacks attachRun; start a fresh session instead");
} Type guard
function supportsMultiRunAttach(s) {
return !!s && typeof s.attachRun === "function";
} Try / catch
try {
await runtime.start({ existingSession: session });
} catch (e) {
if (e.message === "native_session_multi_run_unavailable") {
await runtime.start({}); // fall back to a fresh session
} else throw e;
} Prevention
- Check attachRun exists before passing existingSession
- Upgrade/align the runtime version that persisted the session with the one resuming it
- Confirm provider multi-run support before retaining sessions for reuse
- Persist only sessions produced by attachRun-capable code paths
When it happens
Trigger: Calling the native session runtime with `options.existingSession` set where `existingSession.attachRun === undefined` — i.e. a persisted/retained session produced by an older code path or provider adapter that never exposed attachRun.
Common situations: Resuming sessions created before the attachRun capability was introduced (version skew between persisted state and current runtime); using a provider adapter that does not support multi-run session attachment; a hand-constructed or partially hydrated PersistedNativeSession missing the attach callback.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- ACPX Claude requires Linux x64 or macOS ARM64/x64.
- Adapter declares unsupported UI parser contract version —…
- ${error}
- eval-session nativeResume requires a retained live-session…
- Invalid configured Paperclip API origin
AI-assisted analysis of paperclipai/paperclip@3f1d897a7c (2026-09-18).
Data as JSON: /api/errors/aff82c6f765856e3.
Report an issue: GitHub.
Appendix: source
Thrown at packages/paperclip-runner/src/native-session-runtime.ts:1872
const identity = {
runId: input.binding.runId,
sessionId: normalizedSessionId,
companyId: input.binding.companyId,
issueId: input.binding.issueId,
agentId: input.binding.agentId,
};
let recovered = false;
let session: NativeSession | null = null;
let continuityBreak: {
reason: string;
previousDriverSessionId: string;
previousProviderSessionId: string | null;
} | null = null;
let reconciledRecoveryCheckpoint: PersistedNativeSession | null = null;
await options.onSessionAdmission?.();
if (options.existingSession) {
if (options.existingSession.attachRun === undefined) {
throw new Error("native_session_multi_run_unavailable");
}
// Attaching can fail even after the retained session's identity passes the
// static binding check (for example, when the provider lost multi-run
// state). Prove the provider attachment before opening durable
// control-plane state because ControlPlanePort has no rollback operation.
try {
await options.existingSession.attachRun({ identity });
} catch (error) {
// attachRun has no transactional guarantee: a provider may bind the new
// run before reporting a later failure. Conservatively quarantine the
// session so neither the old nor partially attached run can reuse it.
await quarantineRetainedSession(
options.existingSession,
options.onSession,
"native session attachment failed",
cleanupDomain,
);
throw error;View on GitHub (pinned to 3f1d897a7c)