agalwood/Motrix · warning · AppError

TaskNotFound

TaskNotFound

Error message

task ${taskId} not found

What it means

Thrown by `reopenFileSelection` (magnet-tracker.ts:741) when `db.getTask(taskId)` returns null. The task the caller asked to re-open the magnet file-selection window for does not exist in the database. This guards a stale UI action against a task that was deleted or never created.

Source

Thrown at src/core/torrent/magnet-tracker.ts:741

    entry.hiddenTombstone = true
  }

  /** Re-emit Events.MagnetFileSelection for a task whose metadata already
   *  resolved (aggStatus=MetadataReady) but whose file-selection dialog was
   *  dismissed — so the user can re-open it without re-adding the magnet.
   *  Cache-first (the entry survives onComplete); falls back to the
   *  persisted metadataDir or durable task.torrentMetaPath after a restart
   *  (primeFromDatabase skips MetadataReady rows, so there is no cache entry
   *  then). A no-op
   *  when the task is not MetadataReady (the UI button gates on this state;
   *  this guards a stale click). Throws MagnetResolveFailed when the saved
   *  .torrent is no longer on disk (e.g. an OS reboot cleared the temp dir).
   *  Routing/window handling is identical to the first emit: the bootstrap
   *  forwards MagnetFileSelection to the add-task window. */
  async reopenFileSelection(taskId: string): Promise<void> {
    const pair = this.db.getTask(taskId)
    if (!pair) {
      throw new AppError(ErrorCode.TaskNotFound, `task ${taskId} not found`)
    }
    if (pair.task.aggStatus !== TaskStatus.MetadataReady) {
      log.warn(
        { taskId, status: pair.task.aggStatus },
        'reopenFileSelection ignored: task not in MetadataReady'
      )
      return
    }

    const metaInst = pair.instances.find(
      (i) => i.phase === TaskInstancePhase.MagnetMetadataResolution
    )
    const cached = this.findCacheEntryByTaskId(taskId)
    const metadataDir =
      cached?.metadataDir ??
      (typeof metaInst?.payload.metadataDir === 'string'
        ? metaInst.payload.metadataDir
        : '')

View on GitHub (pinned to 1a708ee577)

Solutions

  1. Have the renderer verify the task still exists (and is MetadataReady) before issuing reopenFileSelection; disable the action on deletion events.
  2. Subscribe to task-deleted events in the renderer and dismiss the selection window.
  3. Treat TaskNotFound as a no-op in the caller (log and close the window) rather than surfacing a hard error to the user.
  4. Double-check the taskId source for typos or stale caches.

Example fix

// before
const pair = this.db.getTask(taskId)
if (!pair) {
  throw new AppError(ErrorCode.TaskNotFound, `task ${taskId} not found`)
}

// after — degrade to a no-op for stale UI clicks
const pair = this.db.getTask(taskId)
if (!pair) {
  log.warn({ taskId }, 'reopenFileSelection ignored: task no longer exists')
  return
}
Defensive patterns

Strategy: validation

Validate before calling

function taskStillExists(db, taskId) { return Boolean(db.getTask(taskId)) }

Type guard

function isTaskNotFound(e) { return e instanceof AppError && e.code === ErrorCode.TaskNotFound }

Try / catch

const pair = this.db.getTask(taskId)
if (!pair) {
  log.warn({ taskId }, 'reopenFileSelection ignored: task no longer exists')
  return // benign no-op for stale UI clicks
}

Prevention

When it happens

Trigger: A stale UI 'select files' click arrives after the task was removed; an IPC call with a wrong/old taskId; a task was cleared by clear-stopped-tasks between the window open and the click; the taskId was fabricated/typoed.

Common situations: Race between user clicking 'select files' and another flow deleting the task; stale renderer state after a clear-all; cross-window IPC with an outdated id; test/dev harness passing a bogus id.

Related errors


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