agalwood/Motrix · error · AppError
TorrentParseFailed
TorrentParseFailed
Error message
Torrent file is too large
What it means
Thrown by torrent-parser.ts:14 when the base64-encoded torrent input exceeds MAX_BASE64_SIZE (50 MiB). TorrentParser.parse guards the parse-torrent library against pathological memory use by rejecting oversized inputs before decoding. The torrent may be otherwise valid; it is simply too large to process.
Source
Thrown at src/core/torrent/torrent-parser.ts:14
import { extname } from 'node:path'
import { getLogger } from '@core/logger'
import { AppError, ErrorCode } from '@shared/errors'
import type { TorrentFileInfo, TorrentMeta } from '@shared/types/torrent'
import parseTorrent from 'parse-torrent'
const log = getLogger('torrent-parser')
const MAX_BASE64_SIZE = 50 * 1024 * 1024
export class TorrentParser {
async parse(base64: string): Promise<TorrentMeta> {
if (base64.length > MAX_BASE64_SIZE) {
throw new AppError(
ErrorCode.TorrentParseFailed,
'Torrent file is too large'
)
}
let parsed: Awaited<ReturnType<typeof parseTorrent>>
try {
const bytes = Buffer.from(base64, 'base64')
parsed = await parseTorrent(new Uint8Array(bytes))
} catch (err) {
log.warn({ err }, 'failed to parse torrent')
throw new AppError(
ErrorCode.TorrentParseFailed,
'Invalid torrent file',
err
)
}
View on GitHub (pinned to 1a708ee577)
Solutions
- Reject the file at the UI layer before reading it entirely — check the source file size and warn the user.
- If the torrent legitimately needs processing, raise MAX_BASE64_SIZE only if memory headroom is confirmed.
- Validate the source is a real `.torrent` and not a duplicated/concatenated payload.
- Prefer passing a Buffer/path to parseTorrent instead of base64 to avoid the 4/3 encoding inflation.
Example fix
// before
if (base64.length > MAX_BASE64_SIZE) {
throw new AppError(ErrorCode.TorrentParseFailed, 'Torrent file is too large')
}
// after — size-check on the raw file before base64 encoding
const stat = await fs.stat(filePath)
if (stat.size > MAX_TORRENT_FILE_SIZE) {
throw new AppError(ErrorCode.TorrentParseFailed, `Torrent file is too large (${stat.size} bytes)`)
} Defensive patterns
Strategy: validation
Validate before calling
const MAX_TORRENT_FILE_SIZE = 50 * 1024 * 1024 // raw bytes
async function torrentWithinSize(fs, filePath) {
const stat = await fs.stat(filePath)
return stat.size <= MAX_TORRENT_FILE_SIZE
}
if (!(await torrentWithinSize(fs, filePath))) {
// reject in the UI before base64-encoding Type guard
function isTorrentTooLarge(e) { return e instanceof AppError && e.code === ErrorCode.TorrentParseFailed && /too large/.test(e.message) } Try / catch
if (base64.length > MAX_BASE64_SIZE) {
throw new AppError(ErrorCode.TorrentParseFailed, `Torrent file is too large (${base64.length} base64 chars)`)
} Prevention
- Check the raw file size before base64-encoding it.
- Pass a Buffer/path to parseTorrent to avoid 4/3 base64 inflation.
- Raise MAX_BASE64_SIZE only if memory headroom is confirmed.
- Reject oversized torrents in the upload UI with a clear message.
When it happens
Trigger: User supplies a `.torrent` whose base64 encoding is > 50 MiB (very large multi-file torrent, or a torrent with huge padding/piece lists); an external caller pushes an oversized payload; the base64 was concatenated/duplicated by a bug.
Common situations: Genuinely huge torrents (massive archives); a malformed caller doubling the base64; a wrapper that embeds the file twice; legacy torrents with extreme piece counts.
Related errors
- aria2 addTorrent gid must contain exactly 16 hexadecimal cha
- invalid-url-scheme
- invalid Chrome extension ID: ${id}
- invalid Firefox extension ID: ${id}
- aria2 returned gid ${actualGid} instead of reserved gid ${re
AI-assisted analysis of agalwood/Motrix@1a708ee577 (2026-08-12).
Data as JSON: /api/errors/7c38e1fed4ad788e.
Report an issue: GitHub.