toeverything/AFFiNE · error · Error

Bad segment: ${mode}

Error message

Bad segment: ${mode}

What it means

Thrown by parsePath after collecting parameters when typeof PARAMS[mode] !== 'number'. PARAMS maps each SVG command letter to its parameter count; if 'mode' is a token text not present in PARAMS (an unsupported/unrecognised command letter), the lookup is undefined and the segment is rejected as 'Bad segment'. This guards against unknown SVG path commands the parser does not support.

Source

Thrown at blocksuite/affine/blocks/surface/src/utils/path-data-parser/parser.ts:116

      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');
    }
  }
  return segments;
}

export function serialize(segments: Segment[]): string {
  const tokens: (string | number)[] = [];
  for (const { key, data } of segments) {
    tokens.push(key);
    switch (key) {
      case 'C':
      case 'c':
        tokens.push(
          data[0],
          `${data[1]},`,

View on GitHub (pinned to 26c515e050)

Solutions

  1. Pre-validate the path string: allow only the SVG path command letters in PARAMS; reject or strip others before parsePath.
  2. Use parsePath's return-early behaviours: note parsePath auto-prepends 'M0,0' for a missing moveto, so ensure the string starts with M/m after any cleanup.
  3. Catch the error and degrade gracefully (default empty path, skip the element).

Example fix

// before
parsePath(rawPath); // rawPath contains 'X' command -> 'Bad segment: X'

// after
const VALID = /^[AaCcHhLlMmQqSsTtVvZz0-9.,\-+eE \t\r\n]+$/;
const safe = VALID.test(rawPath) ? rawPath : 'M0,0';
parsePath(safe);
Defensive patterns

Strategy: validation

Validate before calling

const VALID_PATH = /^[AaCcHhLlMmQqSsTtVvZz0-9.,\-+eE \t\r\n]+$/;
const safe = VALID_PATH.test(rawPath) ? rawPath : 'M0,0';
parsePath(safe);

Type guard

const ALLOWED_CMDS = new Set('AaCcHhLlMmQqSsTtVvZz');
function isKnownCommand(letter) { return ALLOWED_CMDS.has(letter); }

Try / catch

let segments;
try { segments = parsePath(rawPath); }
catch (e) {
  segments = parsePath('M0,0');
}

Prevention

When it happens

Trigger: Calling parsePath with a path string containing a command letter outside the supported set {A,a,C,c,H,h,L,l,M,m,Q,q,S,s,T,t,V,v,Z,z}. For example an 'F', 'X', 'R', or any stray letter treated as a command. The tokenizer accepts single letters as COMMAND tokens, so a stray letter that is not a valid SVG path command reaches this branch.

Common situations: Malformed or hand-authored path strings; exporter bugs emitting non-standard commands; corrupt surface/shape data; copy-paste of non-SVG text into a path field.

Related errors


AI-assisted analysis of toeverything/AFFiNE@26c515e050 (2026-08-12). Data as JSON: /api/errors/58504ebfc3a8135a. Report an issue: GitHub.