{"record":{"id":"f0bfb00fa3d740ea","repo":"koala73/worldmonitor","slug":"recordwavesent-no-ramp-configured","errorCode":null,"errorMessage":"[_recordWaveSent] no ramp configured","messagePattern":"\\[_recordWaveSent\\] no ramp configured","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"convex/broadcast/rampRunner.ts","lineNumber":784,"sourceCode":"/**\n * Internal mutation that the action calls to atomically advance the tier +\n * record a successful wave-send. Validates that the lease still belongs to\n * this runId AND clears all pending-progress markers.\n */\nexport const _recordWaveSent = internalMutation({\n  args: {\n    runId: v.string(),\n    expectedCurrentTier: v.number(),\n    newTier: v.number(),\n    waveLabel: v.string(),\n    broadcastId: v.string(),\n    segmentId: v.string(),\n    assigned: v.number(),\n    sentAt: v.number(),\n  },\n  handler: async (ctx, args) => {\n    const row = await loadConfig(ctx);\n    if (!row) throw new Error(\"[_recordWaveSent] no ramp configured\");\n    if (row.currentTier !== args.expectedCurrentTier) {\n      throw new Error(\n        `[_recordWaveSent] tier moved underneath us: expected ${args.expectedCurrentTier}, found ${row.currentTier}. Refusing to overwrite.`,\n      );\n    }\n    if (row.pendingRunId !== args.runId) {\n      // The lease changed under us — operator force-released it, or\n      // recoverFromPartialFailure cleared it. We must NOT advance the tier;\n      // bubble to Convex auto-Sentry so ops can investigate.\n      throw new Error(\n        `[_recordWaveSent] lease lost: expected runId=${args.runId}, found ${row.pendingRunId ?? \"<cleared>\"}. Refusing to advance tier — investigate what cleared the lease.`,\n      );\n    }\n    await ctx.db.patch(row._id, {\n      currentTier: args.newTier,\n      lastWaveLabel: args.waveLabel,\n      lastWaveBroadcastId: args.broadcastId,\n      lastWaveSegmentId: args.segmentId,","sourceCodeStart":766,"sourceCodeEnd":802,"githubUrl":"https://github.com/koala73/worldmonitor/blob/7d06c8633d256c18e38133030bc3613976a96ec9/convex/broadcast/rampRunner.ts#L766-L802","documentation":"Internal guard in the _recordWaveSent mutation: loadConfig returned no broadcastRampConfig row, so the successful send cannot be recorded and the tier cannot advance. Runner-internal invariant failure — the config existed when the action started, so it was deleted mid-flight or the environment is wrong.","triggerScenarios":"Thrown at convex/broadcast/rampRunner.ts:782 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Check whether broadcastRampConfig was deleted or reset while the wave was being sent","Manually record the send (broadcastId, sentAt) and reconcile tier state before restarting the ramp"],"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"}