agalwood/Motrix · warning · AppError
TaskNotFound
TaskNotFound
Error message
task ${taskId} not found for magnet metadata swap What it means
Thrown by swap-magnet-metadata-for-bt.ts:127 when `db.getTask(taskId)` returns null at the entry of a magnet-metadata-swap operation. The task targeted for swapping its MetadataReady magnet instance for a bt_download instance does not exist.
Source
Thrown at src/core/torrent/swap-magnet-metadata-for-bt.ts:127
input: SwapMagnetMetadataInput,
deps: SwapMagnetMetadataDeps
): Promise<{ gid: string }> {
const { taskId, base64, selectedFiles, saveDir, name } = input
const {
db,
taskManager,
adapter,
magnetTracker,
finalNamePicker,
torrentMetaStore,
publishTaskUpdate,
publishTaskUpdateNow,
recordTransition,
} = deps
const existing = db.getTask(taskId)
if (!existing) {
throw new AppError(
ErrorCode.TaskNotFound,
`task ${taskId} not found for magnet metadata swap`
)
}
if (
magnetTracker.hasPendingSwapCleanup(taskId) ||
existing.instances.some(isMagnetCleanupTombstoneHidden)
) {
throw new AppError(
ErrorCode.MagnetCleanupPending,
`aria2 cleanup for a failed magnet swap is still pending for ` +
`task ${taskId}; please retry confirmation shortly.`
)
}
const previousMetadataInstance =
existing.instances.length === 1 ? existing.instances[0] : undefined
if (View on GitHub (pinned to 1a708ee577)
Solutions
- Verify the task exists in the renderer before showing the swap confirmation, and dismiss the dialog on task-deleted events.
- Treat TaskNotFound as a clean no-op (log + close the window) instead of a hard error.
- Guard the IPC entrypoint with a presence check and return a benign error to the renderer.
- Ensure clear-stopped-tasks and swap cannot run against the same task concurrently.
Example fix
// before
const existing = db.getTask(taskId)
if (!existing) {
throw new AppError(ErrorCode.TaskNotFound, `task ${taskId} not found for magnet metadata swap`)
}
// after — benign no-op for stale confirmations
const existing = db.getTask(taskId)
if (!existing) {
deps.log.warn({ taskId }, 'swap ignored: task no longer exists')
return { outcome: 'noop', reason: 'task_missing' }
} Defensive patterns
Strategy: validation
Validate before calling
function swapTargetExists(db, taskId) { return Boolean(db.getTask(taskId)) } Type guard
function isSwapTaskNotFound(e) { return e instanceof AppError && e.code === ErrorCode.TaskNotFound && /magnet metadata swap/.test(e.message) } Try / catch
const existing = db.getTask(taskId)
if (!existing) {
deps.log.warn({ taskId }, 'swap ignored: task no longer exists')
return { outcome: 'noop', reason: 'task_missing' }
} Prevention
- Verify the task exists in the renderer before showing the swap confirmation.
- Dismiss the swap dialog on task-deleted events.
- Treat TaskNotFound as a benign no-op at this entrypoint.
- Prevent clear-stopped-tasks and swap from racing on the same task.
When it happens
Trigger: Swap requested for a taskId that was deleted between the user confirming and the swap call; a stale UI confirmation window; a typoed/fabricated taskId from an external caller; the task was cleared by clear-stopped-tasks.
Common situations: User confirmed a file selection, then deleted the task before the swap ran; renderer holding a stale task reference after a bulk clear; cross-window IPC with an outdated id.
Related errors
AI-assisted analysis of agalwood/Motrix@1a708ee577 (2026-08-12).
Data as JSON: /api/errors/ac76dfac14bb1aac.
Report an issue: GitHub.