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
- Have the renderer verify the task still exists (and is MetadataReady) before issuing reopenFileSelection; disable the action on deletion events.
- Subscribe to task-deleted events in the renderer and dismiss the selection window.
- Treat TaskNotFound as a no-op in the caller (log and close the window) rather than surfacing a hard error to the user.
- 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
- Disable the 'select files' action in the renderer when the task is deleted.
- Subscribe to task-deleted events and dismiss the selection window.
- Treat TaskNotFound here as a no-op rather than surfacing a hard error.
- Re-check existence immediately before issuing the IPC.
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.