{"record":{"id":"9bafe3bc589ff80e","repo":"siyuan-note/siyuan","slug":"invalid-table-cell-rich-text-payload-9bafe3","errorCode":null,"errorMessage":"invalid table cell rich text payload","messagePattern":"invalid table cell rich text payload","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/treenode/table_cell_rich.go","lineNumber":41,"sourceCode":"\t\tChildren      []json.RawMessage\n\t}\n\tvar check func(json.RawMessage, string) error\n\tcheck = func(raw json.RawMessage, context string) error {\n\t\tvar node rawNode\n\t\tif err := json.Unmarshal(raw, &node); nil != err {\n\t\t\treturn err\n\t\t}\n\t\tif len(node.TableCellRich) > 0 {\n\t\t\tif !utf8.Valid(node.TableCellRich) {\n\t\t\t\treturn fmt.Errorf(\"table cell rich text payload is not UTF-8\")\n\t\t\t}\n\t\t\tversion, _ := strconv.Atoi(spec)\n\t\t\tif version < 4 || node.Type != \"NodeTableCell\" || context != \"row\" {\n\t\t\t\treturn fmt.Errorf(\"invalid table cell rich text document spec [%s]\", spec)\n\t\t\t}\n\t\t\tvar fields map[string]json.RawMessage\n\t\t\tif err := json.Unmarshal(node.TableCellRich, &fields); nil != err || len(fields) != 3 {\n\t\t\t\treturn fmt.Errorf(\"invalid table cell rich text payload\")\n\t\t\t}\n\t\t\tfor _, name := range []string{\"spec\", \"format\", \"content\"} {\n\t\t\t\tif len(fields[name]) == 0 || bytes.Equal(bytes.TrimSpace(fields[name]), []byte(\"null\")) {\n\t\t\t\t\treturn fmt.Errorf(\"missing table cell rich text field [%s]\", name)\n\t\t\t\t}\n\t\t\t}\n\t\t\tvar rich ast.TableCellRich\n\t\t\tif err := json.Unmarshal(node.TableCellRich, &rich); nil != err {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tif _, err := av.ParseTableCellRich(&rich); nil != err {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t\tchildContext := \"\"\n\t\tswitch node.Type {\n\t\tcase \"NodeTable\":\n\t\t\tchildContext = \"table\"","sourceCodeStart":23,"sourceCodeEnd":59,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/treenode/table_cell_rich.go#L23-L59","documentation":"A valid TableCellRich payload must be a JSON object with exactly three fields: spec, format, and content. If the payload fails to unmarshal as an object or has a field count other than 3, this error is thrown.","triggerScenarios":"checkTableCellRichJSON parses a TableCellRich value that is not a JSON object (array/string/number) or an object with fewer/more than 3 keys — e.g. a hand-written payload with only {content} or extra metadata keys.","commonSituations":"Third-party generators producing an outdated or partial rich-text payload shape; manual edits to .sy JSON; mixing payload formats between kernel versions.","solutions":["Regenerate the payload with exactly the three required keys: spec, format, content.","Remove extra keys or add the missing ones so len(fields) == 3.","Restore the document from history/backup if the payload was corrupted by an unknown tool."],"exampleFix":"// before\n{\"content\": \"text\"}\n// after\n{\"spec\": \"4\", \"format\": \"markdown\", \"content\": \"text\"}","handlingStrategy":"validation","validationCode":"const keys = Object.keys(payload);\nif (keys.length !== 3 || !['spec','format','content'].every(k => k in payload)) { /* reject payload before writing */ }","typeGuard":"function isTableCellRichPayload(v) {\n  return v !== null && typeof v === 'object' && !Array.isArray(v) &&\n    Object.keys(v).length === 3 && 'spec' in v && 'format' in v && 'content' in v;\n}","tryCatchPattern":null,"preventionTips":["Serialize payloads through the official schema so exactly spec/format/content are written.","Avoid hand-editing .sy JSON.","Round-trip test generated payloads with the kernel validator."],"tags":["tables","rich-text","json","schema"],"backgroundTag":"schema-validation-failed","analyzedSha":"9f775e8a12daef8255556097396f9b2739078892","analyzedAt":"2026-09-19T03:17:15.984Z","contentChangedAt":"2026-09-19T03:17:15.984Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}