agalwood/Motrix · error · RangeError
Paused must transition from active to paused
Error message
Paused must transition from active to paused
What it means
For `TaskHistoryEventKind.Paused`, all three must hold: `fromStatus` is non-null, `fromStatus` is in `ACTIVE_RESUME_STATUSES` (`fetching_metadata`, `downloading`, `finalizing`, `seeding`), and `toStatus === TaskStatus.Paused`. Throws this `RangeError` otherwise — you cannot pause from an already-paused, terminal, or queued state.
Source
Thrown at src/core/inspector-activity/validators.ts:218
switch (input.kind) {
case TaskHistoryEventKind.Added:
if (input.fromStatus !== null) {
throw new RangeError('Added must not have a fromStatus')
}
break
case TaskHistoryEventKind.Started:
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')View on GitHub (pinned to 1a708ee577)
Solutions
- Only emit Paused when the prior status is active and the new status is paused; otherwise emit the matching kind (or drop the event).
- Track the persisted status and compare before emitting.
- Quarantine out-of-order events during recovery.
Example fix
// before
emit({ kind: TaskHistoryEventKind.Paused, fromStatus: TaskStatus.Paused, toStatus: TaskStatus.Paused })
// after
if (currentStatus === TaskStatus.Paused) return // already paused, no-op
emit({ kind: TaskHistoryEventKind.Paused, fromStatus: currentStatus, toStatus: TaskStatus.Paused }) Defensive patterns
Strategy: validation
Validate before calling
const ACTIVE = new Set([TaskStatus.FetchingMetadata, TaskStatus.Downloading, TaskStatus.Finalizing, TaskStatus.Seeding])
function canPause(from: TaskStatus | null): boolean {
return from !== null && ACTIVE.has(from)
} Prevention
- Emit Paused only from a known-active prior status.
- Drop no-op pauses (fromStatus already Paused).
- Replay events in ordinal order during recovery.
When it happens
Trigger: A Paused event whose `fromStatus` is itself `paused` (double-pause), `completed`/`error` (pausing a terminal task), or `null`, or whose `toStatus` is not `paused` — typically the producer forwarded an engine pause notification without checking the prior status.
Common situations: Engine-level pause/idle signals arriving after the task already transitioned terminal; replaying events out of order; tests that don't set fromStatus.
Related errors
- Added must not have a fromStatus
- Started must enter an active status
- Resumed must transition from paused to active
- 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/eb215cce06f1188f.
Report an issue: GitHub.