agalwood/Motrix · error · AppError

MagnetCleanupPending

MagnetCleanupPending

Error message

aria2 cleanup for a failed magnet swap is still pending for task ${taskId}; please retry confirmation shortly.

What it means

Thrown by swap-magnet-metadata-for-bt.ts:137 when either `magnetTracker.hasPendingSwapCleanup(taskId)` is true or one of the task's instances is a hidden magnet-cleanup tombstone. A previous swap failed and aria2 cleanup of the orphaned GID is still quarantined, so starting a new swap now would create a sibling GID while the old one is still being torn down.

Source

Thrown at src/core/torrent/swap-magnet-metadata-for-bt.ts:137

    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 (
    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`
    )

View on GitHub (pinned to 1a708ee577)

Solutions

  1. Wait a short interval and retry — the cleanup worker reaps the quarantine and the tombstone clears automatically.
  2. Confirm aria2 is healthy and reachable so the pending cleanup can complete.
  3. Surface a user-facing 'cleanup in progress, retry shortly' message instead of a raw error.
  4. Disable the confirm button while `magnetTracker.hasPendingSwapCleanup(taskId)` is true.

Example fix

// before
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.`)
}

// after — UI-driven backoff retry
async function swapWithBackoff(taskId, deps) {
  for (let attempt = 0; attempt < 5; attempt++) {
    try { return await swapMagnetMetadata(taskId, deps) }
    catch (e) {
      if (e instanceof AppError && e.code === ErrorCode.MagnetCleanupPending && attempt < 4) {
        await delay(1000 * (attempt + 1)); continue
      }
      throw e
    }
  }
}
Defensive patterns

Strategy: retry

Validate before calling

function swapCleanupDone(magnetTracker, existing, taskId) {
  return !magnetTracker.hasPendingSwapCleanup(taskId)
    && !existing.instances.some(isMagnetCleanupTombstoneHidden)
}

Type guard

function isSwapCleanupPending(e) { return e instanceof AppError && e.code === ErrorCode.MagnetCleanupPending && /failed magnet swap/.test(e.message) }

Try / catch

for (let attempt = 0; attempt < 5; attempt++) {
  try { return await swapMagnetMetadata(taskId, deps) }
  catch (e) {
    if (e instanceof AppError && e.code === ErrorCode.MagnetCleanupPending && attempt < 4) {
      await delay(1000 * (attempt + 1)); continue
    }
    throw e
  }
}

Prevention

When it happens

Trigger: User retries the swap immediately after a previous failed swap whose aria2 RPC cleanup returned 'quarantined'; a transient RPC failure left the swap cleanup tombstone in place; the magnet-cleanup worker has not yet finished reaping the old GID.

Common situations: Impatient retry after a failed swap; aria2 briefly unreachable (RPC timeout) during cleanup; rapid double-click of the confirm button.

Related errors


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