{"record":{"id":"bb8b4b1ff605b006","repo":"paperclipai/paperclip","slug":"prp-command-type-command-status-json-stri","errorCode":null,"errorMessage":"PRP command ${type} ${command.status}: ${JSON.stringify(command.result)}","messagePattern":"PRP command (.+?) (.+?): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/paperclip-runner/src/live/runnerd-codex-transport.ts","lineNumber":5550,"sourceCode":"    throw new Error(\"runnerd did not report its provider identity\");\n  }\n\n  async #waitCommand(\n    type: string,\n    commandId?: string,\n    deadline = Date.now() + 30_000,\n  ): Promise<void> {\n    while (Date.now() < deadline) {\n      this.#throwIfFailed();\n      const command =\n        commandId === undefined\n          ? this.#core?.store.state.commands.find(\n              (candidate) => candidate.type === type,\n            )\n          : this.#core?.getCommand(commandId);\n      if (command?.status === \"completed\") return;\n      if (command !== undefined && command.status !== \"pending\") {\n        throw new Error(\n          `PRP command ${type} ${command.status}: ${JSON.stringify(command.result)}`,\n        );\n      }\n      if (await this.#runnerHasExited())\n        throw new Error(`runnerd exited while waiting for ${type}`);\n      await new Promise((resolveWait) => setTimeout(resolveWait, 10));\n    }\n    throw new Error(\n      `${this.#startupComplete ? \"provider_transport_failed\" : this.#startupFailureCode}: PRP command ${type} timed out`,\n    );\n  }\n\n\n  #pumpEvents(): void {\n    const core = this.#core;\n    // The controller may activate its new epoch before attachRun observes the\n    // confirmed handoff. Never consume either epoch with the other's cursor.\n    if (","sourceCodeStart":5532,"sourceCodeEnd":5568,"githubUrl":"https://github.com/paperclipai/paperclip/blob/01ad8584922b5d85292b1723cae71fa0d9b07a19/packages/paperclip-runner/src/live/runnerd-codex-transport.ts#L5532-L5568","documentation":"Thrown from `#waitCommand` when the awaited PRP command record exists but its status is neither `pending` nor `completed` (e.g. `failed`, `cancelled`, `timeout`). The message embeds the status and the JSON of `command.result`, so the durable failure payload is visible in the error.","triggerScenarios":"Waiting on a command (by explicit `commandId`, or by scanning `store.state.commands` for the first command of the given type when no id is supplied) and observing a terminal non-success status during the 10ms poll loop.","commonSituations":"runnerd rejected the command payload (validation failure recorded in `result`); the codex subprocess failed mid-command; command deadline exceeded inside runnerd; scanning by type when no id is passed picks up an unrelated failed command of the same type.","solutions":["Read the `command.result` JSON embedded in the message — it contains runnerd's reason for the failure; fix the underlying cause and retry.","Retry the command with a fresh commandId.","When a commandId is not supplied, always pass one so the lookup does not match an older failed command of the same type.","Check runnerd logs for the command ID to see the full failure context; restart runnerd if the failure is internal."],"exampleFix":"// before\nconst command = this.#core?.store.state.commands.find((c) => c.type === type);\n// after\nconst command = commandId\n  ? this.#core?.getCommand(commandId)\n  : this.#core?.store.state.commands.find((c) => c.type === type && c.status !== \"failed\");","handlingStrategy":"try-catch","validationCode":"const cmd = core.getCommand(commandId);\nif (cmd && cmd.status !== \"pending\" && cmd.status !== \"completed\") {\n  throw new Error(`command ${commandId} already terminal: ${cmd.status}`);\n}","typeGuard":"function isRetryableCommandFailure(err) {\n  return err instanceof Error && /^PRP command .* (failed|cancelled|timeout):/.test(err.message);\n}","tryCatchPattern":"try {\n  await waitCommand(type, commandId);\n} catch (err) {\n  if (isRetryableCommandFailure(err)) {\n    log.error(\"PRP command failed\", { result: err.message });\n    await requeueCommand(type, payload);\n  } else throw err;\n}","preventionTips":["Always pass an explicit commandId to avoid matching unrelated failed commands.","Validate command payloads against runnerd's schema before queueing.","Log the embedded command.result JSON for every failure."],"tags":["runnerd","command","protocol","durable-state"],"backgroundTag":"api-error-response","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"}