{"record":{"id":"f1434605698c2c6c","repo":"stablyai/orca","slug":"result-result-lifecycle-code","errorCode":"${result.result.lifecycle.code}","errorMessage":"${result.result.lifecycle.reason}","messagePattern":"\\$\\{result\\.result\\.lifecycle\\.reason\\}","errorType":"exception","errorClass":"RuntimeClientError","httpStatus":null,"severity":"error","filePath":"src/cli/handlers/orchestration.ts","lineNumber":595,"sourceCode":"      priority: getOptionalStringFlag(flags, 'priority'),\n      threadId: getOptionalStringFlag(flags, 'thread-id'),\n      payload: getOptionalStructuredMessagePayload(flags),\n      // Why: pane key is the remint-stable sender identity the runtime verifies lifecycle ownership against; older runtimes strip it.\n      senderPaneKey: process.env.ORCA_PANE_KEY || undefined,\n      waitForLifecycleSettlement: type === 'worker_done' ? true : undefined,\n      devMode: isDevCliInvocation()\n    }\n    const dispatchCapability = getOptionalStringFlag(flags, 'dispatch-capability')\n    const result = await callMutation<OrchestrationSendResult>(\n      client,\n      flags,\n      'orchestration.send',\n      sendParams,\n      dispatchCapability ? { orchestrationCapability: dispatchCapability } : undefined\n    )\n    await requireWorkerDoneSettlement(client, type, sendParams.payload, result.result)\n    if ('lifecycle' in result.result && result.result.lifecycle?.action === 'rejected') {\n      throw new RuntimeClientError(result.result.lifecycle.code, result.result.lifecycle.reason)\n    }\n    printResult(result, json, (r) => {\n      if ('message' in r) {\n        return `Sent ${r.message.id}`\n      }\n      if ('relay' in r) {\n        if (r.relay.destination === 'worker') {\n          return `Queued ${r.relay.messageId} for worker Dispatch ${r.relay.dispatchId}`\n        }\n        return `Queued ${r.relay.messageId} for Run home (Dispatch ${r.relay.dispatchId})`\n      }\n      return `Sent ${r.messages.length} messages to ${r.recipients} recipients`\n    })\n  },\n\n  'orchestration check': async ({ flags, client, cwd, json }) => {\n    const wait = flags.has('wait')\n    const peek = flags.has('peek')","sourceCodeStart":577,"sourceCodeEnd":613,"githubUrl":"https://github.com/stablyai/orca/blob/1136503c6a231a16dce8f921f6fadb63d181e8db/src/cli/handlers/orchestration.ts#L577-L613","documentation":"Thrown in 'orchestration send' (line 595) after the orchestration.send RPC returns a result whose lifecycle.action is 'rejected'. Unlike the other errors, both the error code and message are DYNAMIC: they come from result.result.lifecycle.code and result.result.lifecycle.reason produced by the runtime's lifecycle authority (defined by the LifecycleSendResult 'rejected' variant at line 97). Rejection means the runtime accepted the wire request but refused to apply the lifecycle effect — e.g. a duplicate worker_done, a sender that does not own the Dispatch, or an already-settled Dispatch. This fires only after requireWorkerDoneSettlement completes, so settlement timing is already accounted for.","triggerScenarios":"Sending a worker_done for a Dispatch already settled; sending worker_done/heartbeat from a terminal the runtime does not recognize as the worker owner; sending after the Dispatch was released or abandoned; race where two terminals report outcome on the same Dispatch.","commonSituations":"Retrying a worker_done that already succeeded; coordinator and worker both attempting settlement; a stale terminal handle surviving a remint attempting to act as the worker; cross-version runtime that enforces stricter lifecycle ownership.","solutions":["Read the dynamic code/reason in the thrown error to identify the specific rejection (e.g. duplicate, not-owner, already-settled).","Confirm the sender terminal (ORCA_TERMINAL_HANDLE / --from) is the one the runtime assigned as the worker for that Dispatch.","For duplicate worker_done, check whether a prior send already settled; avoid retrying unchanged.","If ownership changed after a remint, re-resolve the worker terminal handle before resending."],"exampleFix":"// before: retrying a settled dispatch unchanged\norca orchestration send --type worker_done --outcome succeeded --to t_worker123 --subject done\n// after: inspect rejection, verify ownership, do not blind-retry\n// catch the error, read err.code + err.message, confirm dispatch is not already settled,\n// then re-resolve the worker handle before resending","handlingStrategy":"try-catch","validationCode":"// No client-side guard exists: the code/reason come from the server lifecycle authority.\n// Best pre-check: confirm the sender terminal owns the Dispatch via orchestration.workerShow\n// and that the Dispatch is not already settled before sending worker_done.","typeGuard":"function isLifecycleRejected(result: unknown): result is { lifecycle: { action: 'rejected'; code: string; reason: string } } {\n  return typeof result === 'object' && result !== null &&\n    (result as any).lifecycle?.action === 'rejected'\n}","tryCatchPattern":"try {\n  const res = await client.call('orchestration.send', params)\n  if (res.result.lifecycle?.action === 'rejected') {\n    const { code, reason } = res.result.lifecycle\n    // branch on code (duplicate / not-owner / already-settled) instead of blind retry\n  }\n} catch (err) {\n  if (err instanceof RuntimeClientError) {\n    // err.code and err.message carry the dynamic rejection reason\n  }\n}","preventionTips":["Never blind-retry a worker_done; inspect the rejection code first.","Verify the sender handle matches the worker assigned to the Dispatch.","Track settlement state locally to avoid duplicate sends.","Re-resolve terminal handles after a remint before resending."],"tags":["cli","orchestration","lifecycle","rpc","runtime","dispatch"],"backgroundTag":null,"analyzedSha":"1136503c6a231a16dce8f921f6fadb63d181e8db","analyzedAt":"2026-08-12T23:15:58.167Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}