{"record":{"id":"1b400bcc2e08a9d3","repo":"paperclipai/paperclip","slug":"prp-codex-transport-is-closed","errorCode":null,"errorMessage":"PRP Codex transport is closed","messagePattern":"PRP Codex transport is closed","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/paperclip-runner/src/live/runnerd-codex-transport.ts","lineNumber":3284,"sourceCode":"                ? createSanitizedAwsAgentCoreEnvironment(\n                    options.environment,\n                    resolve(this.#root, \"codex-home\"),\n                  )\n                : createSanitizedCodexEnvironment(options.environment),\n      ).sort(),\n      diagnostics: [\"lab transport selected authenticated durable PRP\"],\n    };\n  }\n\n  evidence(): CapabilityRunnerdProcessEvidence {\n    return structuredClone(this.#evidence);\n  }\n\n  async request(\n    method: string,\n    params: Record<string, unknown>,\n  ): Promise<Record<string, unknown>> {\n    if (this.#closed) throw new Error(\"PRP Codex transport is closed\");\n    this.#throwIfFailed();\n    if (\n      this.#pendingWarmRecoveryCompletion !== null &&\n      ![\"thread/read\", \"initialize\", \"collaborationMode/list\"].includes(method)\n    ) {\n      throw new Error(\"native_runner_warm_transition_completion_pending\");\n    }\n    if (method === \"initialize\") return { user: {} };\n    if (method === \"thread/start\") return this.#start(params);\n    if (method === \"collaborationMode/list\") {\n      // runnerd negotiates the real Codex preset or the provider-proxy-owned\n      // planning contract during session.open. This transport-level mask\n      // confirms that closed boundary; turn/start remains runner-managed and\n      // never forwards this sentinel to the outer TypeScript driver.\n      return this.options.provider === undefined ||\n        this.options.provider === \"codex\" ||\n        this.options.provider === \"opencode\" ||\n        this.options.provider === \"acpx\"","sourceCodeStart":3266,"sourceCodeEnd":3302,"githubUrl":"https://github.com/paperclipai/paperclip/blob/01ad8584922b5d85292b1723cae71fa0d9b07a19/packages/paperclip-runner/src/live/runnerd-codex-transport.ts#L3266-L3302","documentation":"request() is the JSON-RPC entry point of the PRP Codex transport; once close() has run (#closed is set), every request is rejected because the underlying transport can no longer service calls. This is a lifecycle guard, not a transient failure.","triggerScenarios":"Calling transport.request(method, params) after transport.close() (or process shutdown path) has marked the transport closed.","commonSituations":"In-flight async work issuing follow-up requests during shutdown; callers keeping a transport reference after close; retry logic racing teardown; tests not awaiting close before assertions.","solutions":["Stop issuing requests after close(); check a closed flag in caller code before invoking request().","Reorder shutdown so all pending requests complete before calling close().","Recreate a new transport instance if further requests are needed.","Use a finally/abort signal to cancel request loops when the transport closes."],"exampleFix":"// before\nawait transport.close();\nawait transport.request('thread/read', { threadId }); // throws\n// after\nif (!transport.isClosed()) await transport.request('thread/read', { threadId });","handlingStrategy":"try-catch","validationCode":"if (transport.isClosed?.()) throw new Error('transport already closed; refusing request');","typeGuard":null,"tryCatchPattern":"try {\n  await transport.request(method, params);\n} catch (err) {\n  if ((err as Error).message === 'PRP Codex transport is closed') {\n    transport = createTransport();\n    await transport.request(method, params);\n  } else throw err;\n}","preventionTips":["Track transport lifecycle in one owner module","Cancel in-flight request loops on close via AbortController","Await all pending requests before calling close() in tests and shutdown hooks"],"tags":["lifecycle","closed-transport","shutdown"],"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"}