{"record":{"id":"9ce242b33e544947","repo":"DIYgod/RSSHub","slug":"unsupported-range-typ","errorCode":null,"errorMessage":"unsupported range: ${typ}","messagePattern":"unsupported range: (.+?)","errorType":"exception","errorClass":"InvalidParameterError","httpStatus":503,"severity":"warning","filePath":"lib/routes/telegram/channel-media.ts","lineNumber":121,"sourceCode":"        }\n    );\n    for await (const chunk of chunks) {\n        if (skip >= chunk.length) {\n            skip -= chunk.length;\n            continue;\n        }\n        yield skip ? chunk.subarray(skip) : chunk;\n        skip = 0;\n    }\n}\n\nfunction parseRange(range: string, length: bigInt.BigInteger) {\n    if (!range) {\n        return [];\n    }\n    const [typ, segstr] = range.split('=', 2);\n    if (typ !== 'bytes') {\n        throw new InvalidParameterError(`unsupported range: ${typ}`);\n    }\n    const segs = segstr.split(',').map((s) => s.trim());\n    const parsedSegs: bigInt.BigInteger[][] = [];\n    for (const seg of segs) {\n        const range = seg\n            .split('-', 2)\n            .filter((v) => !!v)\n            .map((v) => bigInt(v));\n        if (range.length < 2) {\n            if (seg.startsWith('-')) {\n                range.unshift(bigInt(0));\n            } else {\n                range.push(length.subtract(bigInt(1)));\n            }\n        }\n        parsedSegs.push(range);\n    }\n    return parsedSegs;","sourceCodeStart":103,"sourceCodeEnd":139,"githubUrl":"https://github.com/DIYgod/RSSHub/blob/bed535e0879dc71c5aff6f1e7bd1ac21ede40115/lib/routes/telegram/channel-media.ts#L103-L139","documentation":"parseRange parses an HTTP Range header and only supports the 'bytes' range unit (RFC 7233). If the token before '=' is anything other than 'bytes' (or the header is malformed so the split yields a different unit), it throws InvalidParameterError with the offending unit.","triggerScenarios":"A client (media player, browser, downloader) sends a Range header like 'items=0-100', 'time=0-5', or a malformed 'range=0-100'. The split('=') yields a unit that is not 'bytes'.","commonSituations":"A custom downloader sends a non-standard range unit; a buggy client prefixes the header value incorrectly; a proxy rewrites Range into an unsupported form.","solutions":["Have the client send a standards-compliant 'Range: bytes=start-end' header.","In parseRange, treat an unknown unit as 'no range' (return []) and serve the full content with 200 instead of throwing, if partial content is optional.","If a non-bytes unit is genuinely needed, extend parseRange to handle it explicitly rather than relying on the throw."],"exampleFix":"// before\nconst [typ, segstr] = range.split('=', 2);\nif (typ !== 'bytes') {\n    throw new InvalidParameterError(`unsupported range: ${typ}`);\n}\n\n// after: ignore unsupported units and serve full content\nconst [typ, segstr] = range.split('=', 2);\nif (typ !== 'bytes') {\n    return []; // caller treats empty as 'no range'\n}","handlingStrategy":"validation","validationCode":"function isBytesRange(range: string | undefined): boolean {\n    return !range || range.toLowerCase().startsWith('bytes=');\n}\n// reject/ignore the request early if the client sent a non-bytes range","typeGuard":"function isBytesRangeHeader(range: string | undefined): boolean {\n    return !range || range.trim().toLowerCase().startsWith('bytes=');\n}","tryCatchPattern":"try {\n    const segs = parseRange(rangeHeader, length);\n    // serve partial or full content based on segs\n} catch (e) {\n    if (e instanceof InvalidParameterError && /unsupported range/.test(e.message)) {\n        // ignore the unsupported Range and serve the full content with 200\n        return fullContent();\n    }\n    throw e;\n}","preventionTips":["Only emit 'Range: bytes=...' from clients (the only unit parseRange supports).","Treat an unsupported range unit as 'no range' rather than an error when partial content is optional.","Validate the header at the HTTP layer before it reaches parseRange."],"tags":["http","range-header","parameter","validation"],"backgroundTag":null,"analyzedSha":"bed535e0879dc71c5aff6f1e7bd1ac21ede40115","analyzedAt":"2026-08-12T19:29:35.364Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}