toeverything/AFFiNE · error
Invalid duration string unit ${ch}
Error message
Invalid duration string unit ${ch} What it means
Thrown by the parse() function in the duration utility when it encounters a character that is not a digit (0-9) and not a recognized duration unit letter. Recognized unit letters are: d (day), w (week), M (month), y (year), h (hour), m (minute), s (second), and the special case 'ms' (milliseconds). Any other character after a number triggers this error.
Source
Thrown at packages/backend/server/src/base/utils/duration.ts:39
109: 'm',
115: 's',
};
function parse(str: string): DurationInput {
let input: DurationInput = {};
let acc = 0;
for (let i = 0; i < str.length; i++) {
const ch = str[i];
const code = ch.charCodeAt(0);
// number [0..9]
if (code >= 48 && code <= 57) {
acc = acc * 10 + code - 48;
} else {
let unit = KnownCharCodeToCharMap[code];
if (!unit) {
throw new Error(`Invalid duration string unit ${ch}`);
}
// look ahead a char for 'ms' checking if unit met 'm'
if (unit === 'm' && str[i + 1] === 's') {
unit = 'ms';
i++;
}
input[unit] = acc;
acc = 0;
}
}
return input;
}
export const Due = {
ms: (dueStr: string | DurationInput) => {View on GitHub (pinned to 26c515e050)
Solutions
- Use single-letter unit abbreviations: d, w, M (month), y, h, m (minute), s, ms.
- Remember the parser is case-sensitive: 'M' = month, 'm' = minute, 's' = second, 'ms' = millisecond.
- Validate duration strings before passing them to the Due functions, or wrap calls in try-catch.
- Alternatively, pass a DurationInput object directly instead of a string (e.g. { h: 1, m: 30 }).
Example fix
// before
Due.ms('5min'); // 'min' -> 'n' is not a unit -> throws
Due.ms('2H'); // uppercase H not recognized -> throws
// after
Due.ms('5m'); // 5 minutes
Due.ms('2h'); // 2 hours
// or pass an object
Due.ms({ minutes: 5 }); // note: key is 'm' not 'minutes' Defensive patterns
Strategy: validation
Validate before calling
const VALID_UNITS = /^[\d]+(ms|[dwMyhms])/;
function isValidDuration(str: string): boolean {
// split into number-unit pairs and validate each
return str.split(/(?<=\D)(?=\d)/).every(part => VALID_UNITS.test(part));
}
if (!isValidDuration(durationStr)) {
throw new Error(`Invalid duration string: ${durationStr}`);
}
Due.ms(durationStr); Type guard
const isParsableDuration = (str: string): boolean => {
try {
Due.parse(str);
return true;
} catch {
return false;
}
}; Try / catch
try {
const ms = Due.ms(durationStr);
} catch (e) {
if (e.message?.includes('Invalid duration string unit')) {
// parse failed; use a default duration or prompt user
const ms = Due.ms('1h'); // fallback
}
} Prevention
- Use single-letter unit abbreviations: d, w, M, y, h, m, s, ms.
- Remember case sensitivity: 'M' is month, 'm' is minute.
- Prefer passing a DurationInput object for programmatic calls to avoid string parsing errors.
- Wrap Due.parse in a try-catch or use a validation helper when accepting user input.
When it happens
Trigger: Calling Due.ms(str), Due.s(str), Due.after(str), or Due.before(str) with a duration string containing an invalid unit character. For example: '5x' (x is not a unit), '10sec' (sec is not recognized — only 's' is), '3min' (min is not recognized — only 'm' is).
Common situations: Passing human-readable duration strings with full word units ('minutes', 'hours', 'days') instead of single-letter abbreviations. Using uppercase letters incorrectly (the parser is case-sensitive: 'M' is month, 'm' is minute, but 'H' or 'S' are not recognized). Typo in a duration string from config or user input.
Related errors
- bad_request
- Invalid config for module [${module}] with key [${key}] Valu
- Failed to read image size
- Param not a number: ${mode},${numbeToken.text}
- Bad segment: ${mode}
AI-assisted analysis of toeverything/AFFiNE@26c515e050 (2026-08-12).
Data as JSON: /api/errors/6658d3ef9771db7c.
Report an issue: GitHub.