agalwood/Motrix · error · RangeError

Started must enter an active status

Error message

Started must enter an active status

What it means

For `TaskHistoryEventKind.Started`, `toStatus` must be one of the active-resume statuses: `fetching_metadata`, `downloading`, `finalizing`, `seeding`. Throws this `RangeError` otherwise — a Started event that lands in `paused`, `completed`, `error`, `queued`, etc., is a logical contradiction.

Source

Thrown at src/core/inspector-activity/validators.ts:209

    input.errorDetailKey,
    'errorDetailKey',
    MAX_ERROR_DETAIL_KEY_LENGTH
  )
  assertBoundedDetailParams(
    input.errorDetailParams,
    'errorDetailParams',
    MAX_ERROR_DETAIL_PARAMS_JSON_LENGTH
  )

  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')
      }

View on GitHub (pinned to 1a708ee577)

Solutions

  1. Only emit Started when the resolved target status is in `ACTIVE_RESUME_STATUSES`.
  2. For other transitions (Paused, Completed, Error) emit the matching kind (`Paused`, `Completed`, `Failed`).
  3. Re-check the engine-to-TaskStatus mapping for `running`/`active`.

Example fix

// before
emit({ kind: TaskHistoryEventKind.Started, fromStatus: null, toStatus: TaskStatus.Paused })
// after
emit({ kind: TaskHistoryEventKind.Paused, fromStatus: TaskStatus.Downloading, toStatus: TaskStatus.Paused })
Defensive patterns

Strategy: validation

Validate before calling

const ACTIVE = new Set([TaskStatus.FetchingMetadata, TaskStatus.Downloading, TaskStatus.Finalizing, TaskStatus.Seeding])
if (input.kind === TaskHistoryEventKind.Started && !ACTIVE.has(input.toStatus))
  throw new Error('Started requires an active toStatus; pick another kind')

Prevention

When it happens

Trigger: Submitting a Started event with `toStatus: TaskStatus.Paused` or `TaskStatus.Queued` — usually because the producer emitted Started on every state change instead of only on actual start, or because a status-translation table mapped the engine's `running` to the wrong target.

Common situations: Engine-bridge code that fires Started whenever aria2 reports activity, regardless of the resolved target status; tests with mismatched fixtures; off-by-one in status mapping.

Related errors


AI-assisted analysis of agalwood/Motrix@1a708ee577 (2026-08-12). Data as JSON: /api/errors/18589584670ef033. Report an issue: GitHub.