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

  1. Validate/sanitise the SVG path string before calling parsePath: ensure numbers use '.' as decimal separator and no stray command letters appear inside parameter runs.
  2. Run the path through a normaliser (e.g. an SVG-path normalise library) before parsing.
  3. 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

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.