agalwood/Motrix · error · RangeError
Resumed must transition from paused to active
Error message
Resumed must transition from paused to active
What it means
For `TaskHistoryEventKind.Resumed`, `fromStatus` must be exactly `TaskStatus.Paused` and `toStatus` must be in `ACTIVE_RESUME_STATUSES`. Throws this `RangeError` otherwise — resuming is only meaningful from a paused state, and resume must land the task back in an active status.
Source
Thrown at src/core/inspector-activity/validators.ts:226
if (!ACTIVE_RESUME_STATUSES.has(input.toStatus)) {
throw new RangeError('Started must enter an active status')
}
break
case TaskHistoryEventKind.Paused:
if (
input.fromStatus === null ||
!ACTIVE_RESUME_STATUSES.has(input.fromStatus) ||
input.toStatus !== TaskStatus.Paused
) {
throw new RangeError('Paused must transition from active to paused')
}
break
case TaskHistoryEventKind.Resumed:
if (
input.fromStatus !== TaskStatus.Paused ||
!ACTIVE_RESUME_STATUSES.has(input.toStatus)
) {
throw new RangeError('Resumed must transition from paused to active')
}
break
case TaskHistoryEventKind.Completed:
if (input.toStatus !== TaskStatus.Completed) {
throw new RangeError('Completed must end in completed')
}
break
case TaskHistoryEventKind.Failed:
if (input.toStatus !== TaskStatus.Error) {
throw new RangeError('Failed must end in error')
}
break
case TaskHistoryEventKind.ObservedState:
if (input.accuracy !== TaskHistoryAccuracy.Recovered) {
throw new RangeError('Observed state must be recovered')
}
break
case TaskHistoryEventKind.StageChanged:View on GitHub (pinned to 1a708ee577)
Solutions
- Only emit Resumed when the persisted status is `paused` and the new status is active.
- Use Started (not Resumed) when transitioning from a non-paused origin.
- Drop no-op resumes.
Example fix
// before
emit({ kind: TaskHistoryEventKind.Resumed, fromStatus: TaskStatus.Downloading, toStatus: TaskStatus.Downloading })
// after
if (currentStatus === TaskStatus.Paused && ACTIVE.has(newStatus)) {
emit({ kind: TaskHistoryEventKind.Resumed, fromStatus: TaskStatus.Paused, toStatus: newStatus })
} Defensive patterns
Strategy: validation
Validate before calling
const ACTIVE = new Set([TaskStatus.FetchingMetadata, TaskStatus.Downloading, TaskStatus.Finalizing, TaskStatus.Seeding])
function canResume(from: TaskStatus | null, to: TaskStatus): boolean {
return from === TaskStatus.Paused && ACTIVE.has(to)
} Prevention
- Emit Resumed only when the persisted status is Paused and target is active.
- Distinguish Start (from null/queued) from Resume (from Paused).
When it happens
Trigger: A Resumed event whose `fromStatus` is `downloading` (resume from active — should be a no-op or a different kind), or whose `toStatus` is `paused`/`completed`/`error`. Usually the producer fired Resumed on every engine `running` notification without checking the prior status.
Common situations: Engine reporting `running` after the persisted status is already active; bridge code conflating resume with start; tests with mismatched transitions.
Related errors
- Added must not have a fromStatus
- Started must enter an active status
- Paused must transition from active to paused
- Completed must end in completed
- Failed must end in error
AI-assisted analysis of agalwood/Motrix@1a708ee577 (2026-08-12).
Data as JSON: /api/errors/d7cf7709b7e6d77b.
Report an issue: GitHub.