agalwood/Motrix · error · AppError
InvalidSelection
InvalidSelection
Error message
task ${taskId} is not a MetadataReady magnet selection What it means
Thrown by swap-magnet-metadata-for-bt.ts:152 when the task is not a MetadataReady magnet selection: it requires `taskType === Magnet`, `aggStatus === MetadataReady`, exactly one instance, that instance's phase to be `MagnetMetadataResolution`, and its status to be `MetadataReady`. Any mismatch rejects the swap as an invalid selection.
Source
Thrown at src/core/torrent/swap-magnet-metadata-for-bt.ts:152
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 (
existing.task.taskType !== TaskType.Magnet ||
existing.task.aggStatus !== TaskStatus.MetadataReady ||
previousMetadataInstance?.phase !==
TaskInstancePhase.MagnetMetadataResolution ||
previousMetadataInstance.status !== TaskStatus.MetadataReady
) {
throw new AppError(
ErrorCode.InvalidSelection,
`task ${taskId} is not a MetadataReady magnet selection`
)
}
const existingFiles = db.getTaskFiles(taskId)
const originalGraph = {
task: existing.task,
instances: existing.instances,
files: existingFiles,
}
const originalDownloadTask = taskRowToDownloadTask(
existing.task,
existing.instances
)
const originalOwner = taskManager.getById(taskId)
const torrentBytes = Buffer.from(base64, 'base64')
// Complete every fallible local preparation step before destructivelyView on GitHub (pinned to 1a708ee577)
Solutions
- Refresh task state in the renderer before showing the swap confirm dialog and only enable it while the task is MetadataReady magnet.
- Subscribe to status/instance-change events and tear down the swap dialog when the task leaves the valid state.
- Treat InvalidSelection as a benign user-facing 'selection no longer valid' notice rather than a hard error.
- Ensure only one swap flow can run per task at a time.
Example fix
// before
if (existing.task.taskType !== TaskType.Magnet || existing.task.aggStatus !== TaskStatus.MetadataReady || previousMetadataInstance?.phase !== TaskInstancePhase.MagnetMetadataResolution || previousMetadataInstance?.status !== TaskStatus.MetadataReady) {
throw new AppError(ErrorCode.InvalidSelection, `task ${taskId} is not a MetadataReady magnet selection`)
}
// after — renderer-side guard so the throw is never reached
const swappable = task.taskType === 'magnet' && task.aggStatus === 'metadata-ready'
ui.setSwapEnabled(taskId, swappable)
if (!swappable) return Defensive patterns
Strategy: validation
Validate before calling
import { TaskType, TaskStatus, TaskInstancePhase } from '@shared/types'
function isSwappableMagnetSelection(task, instances) {
if (task.taskType !== TaskType.Magnet) return false
if (task.aggStatus !== TaskStatus.MetadataReady) return false
if (instances.length !== 1) return false
const inst = instances[0]
return inst.phase === TaskInstancePhase.MagnetMetadataResolution
&& inst.status === TaskStatus.MetadataReady
} Type guard
function isInvalidSelection(e) { return e instanceof AppError && e.code === ErrorCode.InvalidSelection } Try / catch
if (!isSwappableMagnetSelection(existing.task, existing.instances)) {
ui.notifyUser('selection_no_longer_valid')
return { outcome: 'noop', reason: 'invalid_selection' }
} Prevention
- Refresh task state in the renderer before showing the swap dialog.
- Tear down the swap dialog when the task leaves MetadataReady magnet state.
- Treat InvalidSelection as a benign notice rather than a hard error.
- Allow only one swap flow per task at a time.
When it happens
Trigger: Swap requested on a task that already converted to bt_download; a magnet task still resolving metadata (not yet MetadataReady); a non-magnet task type; the metadata instance was already swapped or cancelled leaving multiple instances or a different phase.
Common situations: Stale confirmation window for a task that already moved state; double-swap attempt; user navigated away and back after a state change; IPC replay with outdated task state.
Related errors
AI-assisted analysis of agalwood/Motrix@1a708ee577 (2026-08-12).
Data as JSON: /api/errors/5eae35471d0fce56.
Report an issue: GitHub.