agalwood/Motrix · error · AppError
TaskFinalizeMetaMissing
TaskFinalizeMetaMissing
Error message
Torrent metadata path not set
What it means
Thrown by `readTorrentMeta` (finalize-task.ts:782) when a torrent-like task reaches finalize/seeding but `task.torrentMetaPath` is null/empty. Seeding requires the original `.torrent` bytes, and without a persisted sidecar path the reseed dance cannot run. This is a state/data defect — the task row is inconsistent.
Source
Thrown at src/core/task/actions/finalize-task.ts:782
task: DownloadTask,
previousStatus: TaskStatus,
deps: FinalizeTaskDeps,
occurredAt = Date.now(),
accuracy: TaskActivityAccuracy = TaskActivityAccuracy.Exact
): Promise<void> {
await recordTaskTransitionOrWarn(task, previousStatus, deps, {
occurredAt,
accuracy,
failureMessage: FINALIZE_RECORD_FAILURE_MESSAGE,
})
}
async function readTorrentMeta(
task: DownloadTask,
deps: FinalizeTaskDeps
): Promise<Uint8Array> {
if (!task.torrentMetaPath) {
throw new AppError(
ErrorCode.TaskFinalizeMetaMissing,
'Torrent metadata path not set'
)
}
try {
return await deps.torrentMetaStore.read(task.torrentMetaPath)
} catch (e) {
throw new AppError(
ErrorCode.TaskFinalizeMetaMissing,
`Torrent metadata is missing at ${task.torrentMetaPath}`,
e
)
}
}
async function persistDesiredFinalPath(
task: DownloadTask,
desiredFinalPath: string,View on GitHub (pinned to 1a708ee577)
Solutions
- Audit the create path that produced this task — confirm torrentBytes were supplied and `torrentMetaStore.persist` ran successfully.
- If this is a Magnet task, ensure the metadata-resolution instance persists torrentMetaPath before allowing transition out of MetadataReady.
- For affected rows, mark the task as non-seedable (or complete without seeding) instead of crashing finalize.
- Add a precondition check at finalize entry that rejects seedable BT tasks lacking torrentMetaPath with a clearer error.
Example fix
// before
if (!task.torrentMetaPath) {
throw new AppError(ErrorCode.TaskFinalizeMetaMissing, 'Torrent metadata path not set')
}
// after — degrade gracefully for HTTP-like leak, hard-fail only for seedable BT
if (!task.torrentMetaPath && task.kind === 'bt') {
await failFinalize(task, deps, {
errorMessage: 'Cannot seed: torrent metadata path not set',
errorDetailKey: 'task.error.detail.metaPathMissing',
hookCode: 'TASK_FINALIZE_META_MISSING',
})
throw new AppError(ErrorCode.TaskFinalizeMetaMissing, 'Torrent metadata path not set')
} Defensive patterns
Strategy: validation
Validate before calling
function hasSeedableMetadata(task) {
// Only BT-like tasks need torrentMetaPath for seeding
if (task.kind !== 'bt') return true
return Boolean(task.torrentMetaPath)
}
if (!hasSeedableMetadata(task)) {
// mark non-seedable / skip seeding instead of throwing in finalize
} Type guard
function isMetaPathMissing(e) { return e instanceof AppError && e.code === ErrorCode.TaskFinalizeMetaMissing && /not set/.test(e.message) } Try / catch
if (!task.torrentMetaPath) {
// degrade: complete without seeding rather than crash finalize
await completeWithoutSeeding(task, deps)
return
} Prevention
- Persist torrentMetaPath during create for every BT task before it becomes finalize-eligible.
- Run a data-integrity sweep on migrated rows to backfill missing torrentMetaPath.
- Add a finalize precondition that rejects seedable BT tasks without a path early.
- Audit create paths to ensure torrentBytes were supplied and persisted.
When it happens
Trigger: A BT or Magnet task was created through a path that skipped `torrentMetaStore.persist` (no torrentBytes supplied); a Magnet task whose metadata was resolved in-engine but never written to a sidecar; corrupted/migrated DB row where torrentMetaPath column was dropped.
Common situations: Migration between versions changed how torrentMetaPath is populated; a Magnet task moved directly to Finalizing without the metadata-resolution instance recording the path; manual DB edits or a partial create that failed after the row insert but before persist.
Related errors
- TaskFinalizeMetaMissing
- TaskCreateTorrentMetaFailed
- MagnetResolveFailed
- current exceeds the signed int64 range
- ${label} is not an integer
AI-assisted analysis of agalwood/Motrix@1a708ee577 (2026-08-12).
Data as JSON: /api/errors/c6ba336568177528.
Report an issue: GitHub.