{"record":{"id":"5327feddd25ee194","repo":"koala73/worldmonitor","slug":"markpickcomplete-run-args-runid-is-run-sta","errorCode":null,"errorMessage":"[_markPickComplete] run ${args.runId} is ${run.status}, expected picking","messagePattern":"\\[_markPickComplete\\] run (.+?) is (.+?), expected picking","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"convex/broadcast/waveRuns.ts","lineNumber":620,"sourceCode":"/**\n * Transition a `picking`-status run to `segment-created` after pickWaveAction\n * has finished sampling, persisting, and creating the Resend segment.\n */\nexport const _markPickComplete = internalMutation({\n  args: {\n    runId: v.string(),\n    segmentId: v.string(),\n    totalCount: v.number(),\n    underfilled: v.boolean(),\n  },\n  handler: async (ctx, args) => {\n    const run = await ctx.db\n      .query(\"waveRuns\")\n      .withIndex(\"by_runId\", (q) => q.eq(\"runId\", args.runId))\n      .unique();\n    if (!run) throw new Error(`[_markPickComplete] no run ${args.runId}`);\n    if (run.status !== \"picking\") {\n      throw new Error(\n        `[_markPickComplete] run ${args.runId} is ${run.status}, expected picking`,\n      );\n    }\n    const now = Date.now();\n    await ctx.db.patch(run._id, {\n      status: \"segment-created\",\n      segmentId: args.segmentId,\n      totalCount: args.totalCount,\n      underfilled: args.underfilled,\n      updatedAt: now,\n    });\n    return { ok: true };\n  },\n});\n\n/**\n * Record a pick-phase failure. Lease policy depends on substatus:\n *   - 'empty-pool' clears the lease (terminal no-op; operator may retry next cycle)","sourceCodeStart":602,"sourceCodeEnd":638,"githubUrl":"https://github.com/koala73/worldmonitor/blob/7d06c8633d256c18e38133030bc3613976a96ec9/convex/broadcast/waveRuns.ts#L602-L638","documentation":"State-machine guard in _markPickComplete: the waveRuns row's status is not 'picking' (the actual status is embedded). The transition to 'segment-created' is only legal from 'picking'; a different status means another writer — a competing pick, an operator action, or a prior completion — already moved the run.","triggerScenarios":"Thrown at convex/broadcast/waveRuns.ts:604 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Read the embedded actual status: 'segment-created' or 'sent' means the pick already completed — treat as idempotent success","'failed' or 'purged' means the run was aborted; do not force the transition, start a new wave instead","Prevent concurrent pickWaveAction invocations for the same run (the lease claim should serialize them)"],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"7d06c8633d256c18e38133030bc3613976a96ec9","analyzedAt":"2026-08-21T16:51:25.751Z","contentChangedAt":"2026-08-21T16:51:25.751Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}