agalwood/Motrix · error · AppError
TaskRemoveNotAvailableDuringFinalize
TaskRemoveNotAvailableDuringFinalize
Error message
Cannot remove task while it is being finalized
What it means
Thrown by `removeTaskUnderMutation` (remove-task.ts:89) when the task being removed has `status === TaskStatus.Finalizing`. Removal during the narrow finalize window is forbidden because finalize holds the stale original GID and a concurrent delete could leave a replacement GID live in aria2 after the parent row is gone.
Source
Thrown at src/core/task/actions/remove-task.ts:89
await deps.runTaskMutation([taskId], remove)
}
/**
* The task snapshot and every external side effect must share one admission
* lock. A late lock around only the durable delete lets reAddTask create and
* publish a replacement GID while removal still holds the stale original GID,
* leaving the replacement live in aria2 after the parent row is deleted.
*/
async function removeTaskUnderMutation(
taskId: string,
options: RemoveTaskOptions,
deps: RemoveTaskDeps
): Promise<void> {
const task = getTaskOrWarn(deps, taskId, 'removeTask')
if (!task) return
if (task.status === TaskStatus.Finalizing) {
throw new AppError(
ErrorCode.TaskRemoveNotAvailableDuringFinalize,
'Cannot remove task while it is being finalized'
)
}
// Both removal paths delete the durable parent row under one
// exclusive-persistence window, with the Inspector Activity deletion
// barrier (when wired) installed before the row disappears. The barrier
// ordering is the delicate part — keep it in exactly one place.
const deleteParentBarrier = (publish: () => void): Promise<void> =>
deps.taskPersistence.runExclusivePersistence(async () => {
if (deps.deleteParentTasks) {
await deps.deleteParentTasks([taskId], publish)
} else {
publish()
}
})
View on GitHub (pinned to 1a708ee577)
Solutions
- Retry the remove shortly after the Finalizing window closes (finalize is bounded and short).
- Have the UI hide/disable the remove action while task.status === Finalizing.
- If removal must be forced, wait for the finalize completion event then issue remove.
- In batch clear logic, skip Finalizing tasks and re-sweep them on the next pass.
Example fix
// before
if (task.status === TaskStatus.Finalizing) {
throw new AppError(ErrorCode.TaskRemoveNotAvailableDuringFinalize, 'Cannot remove task while it is being finalized')
}
// after — caller retries with backoff
try {
await removeTask(taskId, {}, deps)
} catch (e) {
if (e instanceof AppError && e.code === ErrorCode.TaskRemoveNotAvailableDuringFinalize) {
await once(statusBus, `task:${taskId}:status`)
return removeTask(taskId, {}, deps)
}
throw e
} Defensive patterns
Strategy: retry
Validate before calling
function canRemoveNow(task) { return task.status !== TaskStatus.Finalizing } Type guard
function isRemoveDuringFinalize(e) { return e instanceof AppError && e.code === ErrorCode.TaskRemoveNotAvailableDuringFinalize } Try / catch
try {
await removeTask(taskId, {}, deps)
} catch (e) {
if (e instanceof AppError && e.code === ErrorCode.TaskRemoveNotAvailableDuringFinalize) {
await once(statusBus, `task:${taskId}:status`) // wait out the finalize window
return removeTask(taskId, {}, deps)
}
throw e
} Prevention
- Hide/disable the remove action in the UI while task.status === Finalizing.
- In batch-clear logic, skip Finalizing tasks and re-sweep on the next pass.
- Wait for the finalize completion event before issuing a forced remove.
- Avoid automation that removes tasks without accounting for the finalize window.
When it happens
Trigger: User or automation issues a remove-task call while finalize is mid-flight (between rename and metadata commit); a bulk 'clear all' races with an active finalize; a UI double-action where the user clicks remove right as a download completes.
Common situations: Race between a completion-triggered finalize and a user remove; scripted cleanup loops that don't account for the Finalizing window; retry-after-failure automation colliding with finalize.
Related errors
- aria2 returned gid ${actualGid} instead of reserved gid ${re
- plugin.fs.too_many_readers
- plugin.storage.cas_mismatch
- TaskFinalizeRenameFailed
- TaskFinalizeMetaMissing
AI-assisted analysis of agalwood/Motrix@1a708ee577 (2026-08-12).
Data as JSON: /api/errors/b20aee4e69b2c914.
Report an issue: GitHub.