{"record":{"id":"009bb16f5582bed4","repo":"DIYgod/RSSHub","slug":"invalid-segment-part","errorCode":null,"errorMessage":"Invalid segment: ${part}","messagePattern":"Invalid segment: (.+?)","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"lib/utils/helpers.ts","lineNumber":60,"sourceCode":"    return searchParamsString ?? new URLSearchParams(searchParams).toString();\n}\n\n/**\n * parse duration string to seconds\n * @param {string} timeStr - duration string like \"01:01:01\" / \"01:01\" / \"59\"\n * @returns {number}       - total seconds\n */\nexport function parseDuration(timeStr: string | undefined | null): number | undefined {\n    if (!timeStr) {\n        return;\n    }\n    const clean = timeStr.trim().replaceAll(/[^\\d:]/g, '');\n    const parts = clean.split(':');\n    let total = 0;\n    for (const [idx, part] of parts.entries()) {\n        const n = Number(part);\n        if (Number.isNaN(n)) {\n            throw new TypeError(`Invalid segment: ${part}`);\n        }\n        total += n * Math.pow(60, parts.length - 1 - idx);\n    }\n    return total;\n}\n","sourceCodeStart":42,"sourceCodeEnd":66,"githubUrl":"https://github.com/DIYgod/RSSHub/blob/bed535e0879dc71c5aff6f1e7bd1ac21ede40115/lib/utils/helpers.ts#L42-L66","documentation":"parseDuration splits a time string on ':' after stripping every character that is not a digit or colon, then Number()-converts each segment. If any segment cannot be parsed as a number the function throws a TypeError naming the offending segment. In practice the sanitisation regex makes non-numeric segments very hard to produce, so this is a defensive guard against unexpected input shapes.","triggerScenarios":"Calling parseDuration with a string that, after replaceAll(/[^\\d:]/g,''), still yields a segment Number() rejects as NaN (e.g. unusual unicode digit separators that survive the regex, or a programmatically-constructed input bypassing the documented formats 'SS', 'MM:SS', 'HH:MM:SS').","commonSituations":"A feed passing a localized duration format (e.g. full-width digits, non-ASCII colon variants) that the strip regex keeps; unit tests feeding adversarial strings; an upstream format change in a media route that hands parseDuration a malformed value.","solutions":["Normalise the input before calling parseDuration: convert full-width digits to ASCII and unicode colons to ':' (e.g. value.normalize('NFKC')).","Wrap the call in try/catch and treat the duration as unknown on failure rather than crashing the route.","Validate with a regex like /^(\\d{1,2}:){0,2}\\d{1,2}$/ before calling parseDuration."],"exampleFix":"// before\nconst seconds = parseDuration(raw);\n// after\nconst seconds = /^[0-9]+(:[0-9]+){0,2}$/.test(raw.trim()) ? parseDuration(raw) : undefined;","handlingStrategy":"validation","validationCode":"function isValidDuration(s: string | null | undefined): boolean {\n  return typeof s === 'string' && /^\\d{1,2}(:\\d{1,2}){0,2}$/.test(s.trim());\n}\n// before calling parseDuration\nif (!isValidDuration(raw)) return undefined;","typeGuard":"const isParsableDuration = (s: unknown): s is string =>\n  typeof s === 'string' && /^\\d{1,2}(:\\d{1,2}){0,2}$/.test(s.trim());","tryCatchPattern":"try {\n  return parseDuration(raw);\n} catch (e) {\n  if (e instanceof TypeError && /Invalid segment/.test(e.message)) return undefined;\n  throw e;\n}","preventionTips":["Normalise input with .normalize('NFKC') to fold full-width digits/colons before parsing.","Validate with a strict regex before calling parseDuration so malformed input never reaches the loop.","Treat duration parsing as best-effort in route code - wrap it and degrade gracefully."],"tags":["utils","parsing","duration","type-error"],"backgroundTag":null,"analyzedSha":"bed535e0879dc71c5aff6f1e7bd1ac21ede40115","analyzedAt":"2026-08-12T19:29:35.364Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}