{"record":{"id":"e4020815d3e47e5e","repo":"agalwood/Motrix","slug":"observed-state-must-be-recovered","errorCode":null,"errorMessage":"Observed state must be recovered","messagePattern":"Observed state must be recovered","errorType":"validation","errorClass":"RangeError","httpStatus":null,"severity":"error","filePath":"src/core/inspector-activity/validators.ts","lineNumber":241,"sourceCode":"        input.fromStatus !== TaskStatus.Paused ||\n        !ACTIVE_RESUME_STATUSES.has(input.toStatus)\n      ) {\n        throw new RangeError('Resumed must transition from paused to active')\n      }\n      break\n    case TaskHistoryEventKind.Completed:\n      if (input.toStatus !== TaskStatus.Completed) {\n        throw new RangeError('Completed must end in completed')\n      }\n      break\n    case TaskHistoryEventKind.Failed:\n      if (input.toStatus !== TaskStatus.Error) {\n        throw new RangeError('Failed must end in error')\n      }\n      break\n    case TaskHistoryEventKind.ObservedState:\n      if (input.accuracy !== TaskHistoryAccuracy.Recovered) {\n        throw new RangeError('Observed state must be recovered')\n      }\n      break\n    case TaskHistoryEventKind.StageChanged:\n      break\n  }\n}\n\nexport function normalizeTransferSamples(\n  samples: readonly TaskTransferSample[]\n): TaskTransferSample[] {\n  return samples.map((sample, index) => ({\n    t: assertPositiveSafeInteger(sample.t, `samples[${index}].t`),\n    down: normalizeSpeed(sample.down, `samples[${index}].down`),\n    up: normalizeSpeed(sample.up, `samples[${index}].up`),\n    flags: (() => {\n      const flags = assertNonNegativeSafeInteger(\n        sample.flags,\n        `samples[${index}].flags`","sourceCodeStart":223,"sourceCodeEnd":259,"githubUrl":"https://github.com/agalwood/Motrix/blob/1a708ee57746c434e2c67a44bbf0906a976afea4/src/core/inspector-activity/validators.ts#L223-L259","documentation":"For `TaskHistoryEventKind.ObservedState`, `accuracy` must be `TaskHistoryAccuracy.Recovered`. ObservedState events are emitted during recovery from a coverage gap, so by definition their data is reconstructed rather than exact. Throws this `RangeError` if accuracy is `Exact`.","triggerScenarios":"Submitting an ObservedState event with `accuracy: 'exact'` — usually because the recovery code reused a live-event builder that defaulted to Exact, or because accuracy was not set explicitly.","commonSituations":"New recovery code paths that forget to flag the event as recovered; tests reusing a live-event fixture for a recovered scenario.","solutions":["Always set `accuracy: TaskHistoryAccuracy.Recovered` when building ObservedState events.","Use a dedicated builder for recovery events that hard-codes the accuracy.","Do not emit ObservedState during live recording — it is recovery-only."],"exampleFix":"// before\nemit({ kind: TaskHistoryEventKind.ObservedState, accuracy: TaskHistoryAccuracy.Exact, /* ... */ })\n// after\nemit({ kind: TaskHistoryEventKind.ObservedState, accuracy: TaskHistoryAccuracy.Recovered, /* ... */ })","handlingStrategy":"validation","validationCode":"if (input.kind === TaskHistoryEventKind.ObservedState)\n  input.accuracy = TaskHistoryAccuracy.Recovered","typeGuard":null,"tryCatchPattern":null,"preventionTips":["ObservedState is recovery-only — always pair it with Recovered accuracy.","Use a dedicated factory for recovery events."],"tags":["validation","range-error","state-machine","recovery"],"backgroundTag":null,"analyzedSha":"1a708ee57746c434e2c67a44bbf0906a976afea4","analyzedAt":"2026-08-12T16:18:09.346Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}