toeverything/AFFiNE · error · Error
Param not a number: ${mode},${numbeToken.text}
Error message
Param not a number: ${mode},${numbeToken.text} What it means
Thrown by parsePath (SVG path-data parser used by the surface renderer) when, while collecting the parameters for a path command, one of the tokens expected to be a NUMBER is not a number token. The parser tokenises an SVG path 'd' string; each command (M/L/C/Q/...) has a fixed parameter count (PARAMS), and after reading the command it iterates the next paramsCount tokens demanding they all be numbers. A non-number token at a parameter position yields this error with the offending mode and token text.
Source
Thrown at blocksuite/affine/blocks/surface/src/utils/path-data-parser/parser.ts:103
paramsCount = PARAMS[token.text];
mode = token.text;
} else {
return parsePath('M0,0' + d);
}
} else if (isType(token, NUMBER)) {
paramsCount = PARAMS[mode];
} else {
index++;
paramsCount = PARAMS[token.text];
mode = token.text;
}
if (index + paramsCount < tokens.length) {
for (let i = index; i < index + paramsCount; i++) {
const numbeToken = tokens[i];
if (isType(numbeToken, NUMBER)) {
params[params.length] = +numbeToken.text;
} else {
throw new Error(
'Param not a number: ' + mode + ',' + numbeToken.text
);
}
}
if (typeof PARAMS[mode] === 'number') {
const segment: Segment = { key: mode, data: params };
segments.push(segment);
index += paramsCount;
token = tokens[index];
if (mode === 'M') mode = 'L';
if (mode === 'm') mode = 'l';
} else {
throw new Error('Bad segment: ' + mode);
}
} else {
throw new Error('Path data ended short');
}
}View on GitHub (pinned to 26c515e050)
Solutions
- Validate/sanitise the SVG path string before calling parsePath: ensure numbers use '.' as decimal separator and no stray command letters appear inside parameter runs.
- Run the path through a normaliser (e.g. an SVG-path normalise library) before parsing.
- Wrap parsePath in try/catch and fall back to a safe default path (or skip the element) on malformed input.
Example fix
// before
parsePath(userPathString); // 'M10,L20' -> throws
// after
try {
parsePath(userPathString);
} catch (e) {
// fall back: skip element or use default path
segments = parsePath('M0,0 L0,0');
} Defensive patterns
Strategy: try-catch
Validate before calling
function normalisePath(d) {
return d.replace(/,/g, ' ').replace(/\s+/g, ' ').trim();
}
// ensure decimal points are '.' and no stray letters inside number runs before parsing
parsePath(normalisePath(rawPath)); Try / catch
let segments;
try { segments = parsePath(rawPath); }
catch (e) {
// fall back to a safe default path
segments = parsePath('M0,0 L0,0');
} Prevention
- Validate SVG path strings before parsing; reject unknown letters inside parameter runs.
- Normalise number formatting (use '.' as decimal separator).
- Wrap parsePath in try/catch and degrade to a default path on malformed input.
When it happens
Trigger: Calling parsePath(d) with a malformed SVG path string where a letter/command appears where a number is expected, e.g. 'M10,L20' (a stray command mid-params) or 'L 10 x 20'. Also when the tokenizer falls through because the regex could not classify a token but the upper bound check still passes.
Common situations: Loading a shape/mindmap/connector whose path data is hand-edited or produced by a buggy exporter; copy-pasting SVG path strings from external sources; corrupt surface block data; locale-specific number formatting (comma decimal separators) mis-tokenised.
Related errors
AI-assisted analysis of toeverything/AFFiNE@26c515e050 (2026-08-12).
Data as JSON: /api/errors/04eadb34d3081fe8.
Report an issue: GitHub.