DIYgod/RSSHub · error · TypeError
Invalid segment: ${part}
Error message
Invalid segment: ${part} What it means
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.
Source
Thrown at lib/utils/helpers.ts:60
return searchParamsString ?? new URLSearchParams(searchParams).toString();
}
/**
* parse duration string to seconds
* @param {string} timeStr - duration string like "01:01:01" / "01:01" / "59"
* @returns {number} - total seconds
*/
export function parseDuration(timeStr: string | undefined | null): number | undefined {
if (!timeStr) {
return;
}
const clean = timeStr.trim().replaceAll(/[^\d:]/g, '');
const parts = clean.split(':');
let total = 0;
for (const [idx, part] of parts.entries()) {
const n = Number(part);
if (Number.isNaN(n)) {
throw new TypeError(`Invalid segment: ${part}`);
}
total += n * Math.pow(60, parts.length - 1 - idx);
}
return total;
}
View on GitHub (pinned to bed535e087)
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.
Example fix
// before
const seconds = parseDuration(raw);
// after
const seconds = /^[0-9]+(:[0-9]+){0,2}$/.test(raw.trim()) ? parseDuration(raw) : undefined; Defensive patterns
Strategy: validation
Validate before calling
function isValidDuration(s: string | null | undefined): boolean {
return typeof s === 'string' && /^\d{1,2}(:\d{1,2}){0,2}$/.test(s.trim());
}
// before calling parseDuration
if (!isValidDuration(raw)) return undefined; Type guard
const isParsableDuration = (s: unknown): s is string =>
typeof s === 'string' && /^\d{1,2}(:\d{1,2}){0,2}$/.test(s.trim()); Try / catch
try {
return parseDuration(raw);
} catch (e) {
if (e instanceof TypeError && /Invalid segment/.test(e.message)) return undefined;
throw e;
} Prevention
- 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.
When it happens
Trigger: 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').
Common situations: 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.
Related errors
- 无法解析页面数据,请检查漫画 ID 是否正确或页面结构是否变动
- 无法解析页面 Props 数据
- 无法解析页面 HTML 数据,可能触发了反爬策略或页面结构巨变
- 无法在 HTML 缓存中提取核心数据对象
- 成功获取数据对象,但未找到作品基本信息
AI-assisted analysis of DIYgod/RSSHub@bed535e087 (2026-08-12).
Data as JSON: /api/errors/009bb16f5582bed4.
Report an issue: GitHub.