{"record":{"id":"58504ebfc3a8135a","repo":"toeverything/AFFiNE","slug":"bad-segment-mode","errorCode":null,"errorMessage":"Bad segment: ${mode}","messagePattern":"Bad segment: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"blocksuite/affine/blocks/surface/src/utils/path-data-parser/parser.ts","lineNumber":116,"sourceCode":"      for (let i = index; i < index + paramsCount; i++) {\n        const numbeToken = tokens[i];\n        if (isType(numbeToken, NUMBER)) {\n          params[params.length] = +numbeToken.text;\n        } else {\n          throw new Error(\n            'Param not a number: ' + mode + ',' + numbeToken.text\n          );\n        }\n      }\n      if (typeof PARAMS[mode] === 'number') {\n        const segment: Segment = { key: mode, data: params };\n        segments.push(segment);\n        index += paramsCount;\n        token = tokens[index];\n        if (mode === 'M') mode = 'L';\n        if (mode === 'm') mode = 'l';\n      } else {\n        throw new Error('Bad segment: ' + mode);\n      }\n    } else {\n      throw new Error('Path data ended short');\n    }\n  }\n  return segments;\n}\n\nexport function serialize(segments: Segment[]): string {\n  const tokens: (string | number)[] = [];\n  for (const { key, data } of segments) {\n    tokens.push(key);\n    switch (key) {\n      case 'C':\n      case 'c':\n        tokens.push(\n          data[0],\n          `${data[1]},`,","sourceCodeStart":98,"sourceCodeEnd":134,"githubUrl":"https://github.com/toeverything/AFFiNE/blob/b4c8548c09da21b2898443559a5b846f0ccf5dd8/blocksuite/affine/blocks/surface/src/utils/path-data-parser/parser.ts#L98-L134","documentation":"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.","triggerScenarios":"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.","commonSituations":"Optional chaining / ?? producing null defaults; API responses containing explicit nulls stored directly; state objects initialized with null fields.","solutions":["Send a real value for the field, or omit the key entirely — undefined keys are dropped automatically before validation","If the field may legitimately be empty, declare it optional: true in the table schema","Normalize payloads before write: delete keys whose value is null when you mean 'absent'"],"exampleFix":"// before\ntable.insert({ data: { id: 'a1', title: null } }); // title is not optional\n\n// after\ntable.insert({ data: { id: 'a1', title: 'hello' } });\n// or omit the key (undefined fields are dropped):\ntable.insert({ data: { id: 'a1' } });\n// or relax the schema: title: { type: 'string', optional: true }","handlingStrategy":"validation","validationCode":"function normalizeNulls(data: Record<string, any>, schema: Record<string, { optional?: boolean }>) {\n  for (const [key, value] of Object.entries(data)) {\n    if (value === null && !schema[key]?.optional) {\n      delete data[key]; // or throw with your own field-level message\n    }\n  }\n  return data;\n}","typeGuard":"null","tryCatchPattern":null,"preventionTips":["Omit keys entirely rather than sending null for absent values — undefined keys are dropped silently","Mark fields optional: true in the schema when empty is legitimate","Strip nulls from API/form payloads before writes"],"tags":["orm","database","schema-validation","null","not-null"],"backgroundTag":"not-null-constraint-violation","analyzedSha":"b4c8548c09da21b2898443559a5b846f0ccf5dd8","analyzedAt":"2026-08-18T21:16:52.546Z","contentChangedAt":"2026-08-18T21:16:52.546Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}