{"record":{"id":"eae5d21f22348e14","repo":"paperclipai/paperclip","slug":"acpx-session-ensure-non-error","errorCode":"ACPX_SESSION_ENSURE_NON_ERROR","errorMessage":"ACPX session ensure rejected a non-error","messagePattern":"ACPX session ensure rejected a non-error","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/paperclip-runner/src/drivers/acpx/codex-runtime-adapter.ts","lineNumber":469,"sourceCode":"  }\n}\n\n/** Backward-compatible name retained for existing Codex-only consumers. */\nexport const openCodexAcpxRuntime = openQualifiedAcpxRuntime;\n\nfunction classifySessionEnsureFailure(error: unknown): Error {\n  if (error instanceof Error) {\n    const details = error as Error & Record<string, unknown>;\n    if (typeof details.code !== \"string\" || details.code.length === 0) {\n      details.code =\n        error instanceof TypeError\n          ? \"ACPX_SESSION_ENSURE_TYPE_ERROR\"\n          : \"ACPX_SESSION_ENSURE_FAILED\";\n    }\n    return error;\n  }\n  return Object.assign(new Error(\"ACPX session ensure rejected a non-error\"), {\n    code: \"ACPX_SESSION_ENSURE_NON_ERROR\",\n  });\n}\n\nfunction raceRuntimeHandshakeWithAbort<T>(\n  handshake: Promise<T>,\n  signal: AbortSignal,\n): Promise<T> {\n  signal.throwIfAborted();\n  return new Promise<T>((resolve, reject) => {\n    let settled = false;\n    const settle = (operation: () => void): void => {\n      if (settled) return;\n      settled = true;\n      signal.removeEventListener(\"abort\", onAbort);\n      operation();\n    };\n    const onAbort = (): void => settle(() => reject(signal.reason));\n    signal.addEventListener(\"abort\", onAbort, { once: true });","sourceCodeStart":451,"sourceCodeEnd":487,"githubUrl":"https://github.com/paperclipai/paperclip/blob/01ad8584922b5d85292b1723cae71fa0d9b07a19/packages/paperclip-runner/src/drivers/acpx/codex-runtime-adapter.ts#L451-L487","documentation":"classifySessionEnsureFailure converts whatever the ACPX session-ensure operation threw into a typed error. If the rejected value is not an Error instance, it cannot be classified as TYPE_ERROR or FAILED, so this fallback Error with code ACPX_SESSION_ENSURE_NON_ERROR is produced. It indicates the underlying runtime rejected the promise with a non-Error value (string, object, undefined).","triggerScenarios":"The ACPX handshake/session-ensure promise rejects with a string, plain object, or undefined instead of an Error, e.g. a runtime bug, a cross-realm throw, or a host process crashing and rejecting with a serialized payload.","commonSituations":"Mixed Node versions or bundled runtimes throwing non-Error values; IPC layer rejecting with raw payload objects; third-party ACPX runtime updates changing rejection values.","solutions":["Inspect the runtime logs to find the original rejection value; the non-Error value usually carries the real cause.","Coerce rejections to Errors at the boundary (Promise catch mapping or util.toError) in the ACPX host.","Pin/upgrade the ACPX runtime to a version that rejects with proper Error objects.","Check that the host process/child runtime did not crash mid-handshake; fix the crash before the classification layer matters."],"exampleFix":"// before\nreject({ reason: \"spawn failed\" }); // runtime rejects non-Error\n// after\nreject(new Error(\"spawn failed\")); // classifySessionEnsureFailure can classify it","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"function isError(v) {\n  return v instanceof Error;\n}","tryCatchPattern":"try {\n  await driver.handshake();\n} catch (err) {\n  if (err.code === \"ACPX_SESSION_ENSURE_NON_ERROR\") {\n    // log err.stack and inspect raw runtime logs for the original rejection value\n  } else throw err;\n}","preventionTips":["Always reject promises with Error instances in the ACPX host boundary.","Pin and test against a known ACPX runtime version.","Log unclassified rejection values at the source for easier diagnosis.","Handle child-process crashes during handshake explicitly."],"tags":["codex","acpx","handshake","error-classification"],"backgroundTag":"unexpected-response-shape","analyzedSha":"01ad8584922b5d85292b1723cae71fa0d9b07a19","analyzedAt":"2026-09-10T03:14:50.855Z","contentChangedAt":"2026-09-10T03:14:50.855Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}