{"record":{"id":"ec072bb1c119ded1","repo":"paperclipai/paperclip","slug":"runner-prp-command-outcome-status-command-com","errorCode":null,"errorMessage":"runner_prp_command_${outcome.status}:${command.commandId}","messagePattern":"runner_prp_command_(.+?):(.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"server/src/realtime/runner-prp-ws.ts","lineNumber":216,"sourceCode":"  );\n  return {\n    runId,\n    commandId: command.commandId,\n    controllerSeq: command.controllerSeq,\n    completion: (async () => {\n      const deadline = Date.now() + 30_000;\n      while (Date.now() < deadline) {\n        const outcome = binding.authority.commandOutcome(command.commandId);\n        if (!outcome) {\n          throw new Error(`runner_prp_command_missing:${command.commandId}`);\n        }\n        if (outcome.status === \"completed\") return outcome.result;\n        if (outcome.status === \"failed\" || outcome.status === \"rejected\") {\n          const message =\n            outcome.result && typeof outcome.result.message === \"string\"\n              ? outcome.result.message\n              : `runner_prp_command_${outcome.status}:${command.commandId}`;\n          throw new Error(message);\n        }\n        await new Promise<void>((resolve) => {\n          const timer = setTimeout(resolve, 10);\n          timer.unref();\n        });\n      }\n      throw new Error(`runner_prp_command_timeout:${command.commandId}`);\n    })(),\n  };\n}\n\nexport class RunnerPrpRuntimeRequestResolutionError extends Error {\n  constructor(\n    readonly code:\n      | \"runner_prp_authority_not_active\"\n      | \"runtime_request_resolution_conflict\",\n  ) {\n    super(code);","sourceCodeStart":198,"sourceCodeEnd":234,"githubUrl":"https://github.com/paperclipai/paperclip/blob/01ad8584922b5d85292b1723cae71fa0d9b07a19/server/src/realtime/runner-prp-ws.ts#L198-L234","documentation":"When the authority reports a queued PRP command as failed or rejected, queueLiveRunnerPrpCommand throws with the outcome's message if it is a string, otherwise this synthesized 'runner_prp_command_<status>:<commandId>' message. It surfaces the remote command outcome to the steering caller.","triggerScenarios":"steer/nativeControl command is delivered but the runner authority completes it with status failed or rejected and no string message in outcome.result.","commonSituations":"Runner rejected a steer because the turn was busy or in an invalid state; native control command failed on the runner; runner returned a non-string error payload.","solutions":["Read the status embedded in the message (failed vs rejected) to decide retry vs abort","Inspect runner logs for the commandId to find the underlying failure","Resend the command if the failure was transient; do not resend if rejected due to run state","Have the runner return a string result.message so callers get actionable errors"],"exampleFix":"// before\nawait steer(runId, text); // throws runner_prp_command_failed:<id>\n// after\ntry {\n  await steer(runId, text);\n} catch (e) {\n  if (String(e.message).startsWith('runner_prp_command_rejected')) {\n    // run state rejected it; do not blind-retry\n  } else if (String(e.message).startsWith('runner_prp_command_failed')) {\n    await steer(runId, text); // transient; retry\n  } else throw e;\n}","handlingStrategy":"try-catch","validationCode":"// check run turn state before steering\nconst state = await getRunState(runId); if (state.busy) await waitForIdle(runId);","typeGuard":"const hasMessage = (r) => !!r && typeof r.message === 'string';","tryCatchPattern":"try { await steer(runId, text) } catch (e) { if (/runner_prp_command_rejected/.test(e.message)) abort(); else if (/runner_prp_command_failed/.test(e.message)) retryOnce(); else throw e; }","preventionTips":["Have runners always return a string result.message for failed/rejected outcomes","Check run/turn state before sending steer or native-control commands","Distinguish rejected (state conflict, do not retry) from failed (transient, retry)","Correlate commandId with runner logs when diagnosing outcomes"],"tags":["websocket","command","remote-execution"],"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-14T00:17:10.932Z"}