toeverything/AFFiNE · error

Bad segment

Error message

Bad segment: ${mode}

What it means

DataTypeShouldMatch treats undefined field values as 'not provided' (silently deleted from the payload) but an explicit null as a real value; when the schema field is not optional, null fails with 'Field ... is required but not set'. This mirrors SQL NOT NULL semantics: absent is fine, present-but-empty is not.

Solutions

  1. Send a real value for the field, or omit the key entirely — undefined keys are dropped automatically before validation
  2. If the field may legitimately be empty, declare it optional: true in the table schema
  3. Normalize payloads before write: delete keys whose value is null when you mean 'absent'

Example fix

// before
table.insert({ data: { id: 'a1', title: null } }); // title is not optional

// after
table.insert({ data: { id: 'a1', title: 'hello' } });
// or omit the key (undefined fields are dropped):
table.insert({ data: { id: 'a1' } });
// or relax the schema: title: { type: 'string', optional: true }
Defensive patterns

Strategy: validation

Validate before calling

function normalizeNulls(data: Record<string, any>, schema: Record<string, { optional?: boolean }>) {
  for (const [key, value] of Object.entries(data)) {
    if (value === null && !schema[key]?.optional) {
      delete data[key]; // or throw with your own field-level message
    }
  }
  return data;
}

Type guard

null

Prevention

When it happens

Trigger: Inserting { title: null } where the schema declares title: { type: 'string' } without optional: true; form serializers writing nulls for empty inputs; storing parsed JSON whose null literals survive into the write path; 'clearing' a field by assigning null instead of deleting the key.

Common situations: Optional chaining / ?? producing null defaults; API responses containing explicit nulls stored directly; state objects initialized with null fields.

Related errors


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

Appendix: 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 b4c8548c09)