siyuan-note/siyuan · error

missing table cell rich text field

Error message

missing table cell rich text field [%s]

What it means

After the field-count check, each of the three required TableCellRich fields (spec, format, content) must be present, non-empty, and not JSON null. A missing/empty/null field yields this error naming the field.

Solutions

  1. Populate all three fields with non-null values: spec (e.g. "4"), a valid format identifier, and the cell content string.
  2. Fix the generating code so it never emits empty/null for these fields.
  3. Restore the affected document from snapshot/history if the null fields come from data corruption.

Example fix

// before
{"spec":"4","format":null,"content":"x"}
// after
{"spec":"4","format":"markdown","content":"x"}
Defensive patterns

Strategy: validation

Validate before calling

if (!payload.spec || !payload.format || payload.content == null) { /* reject before writing */ }

Type guard

function hasAllRichFields(v) {
  return typeof v === 'object' && v !== null &&
    v.spec != null && v.spec !== '' && v.format != null && v.format !== '' && v.content != null;
}

Prevention

When it happens

Trigger: A TableCellRich payload object containing keys with empty values, explicit null, or omitting one of spec/format/content entirely, e.g. {"spec":"4","format":"","content":"x"}.

Common situations: Producers that write empty strings for unset fields, serialization dropping default values, or partial writes/truncation leaving a field null.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19). Data as JSON: /api/errors/735d372897b746be. Report an issue: GitHub.

Appendix: source

Thrown at kernel/treenode/table_cell_rich.go:45

		var node rawNode
		if err := json.Unmarshal(raw, &node); nil != err {
			return err
		}
		if len(node.TableCellRich) > 0 {
			if !utf8.Valid(node.TableCellRich) {
				return fmt.Errorf("table cell rich text payload is not UTF-8")
			}
			version, _ := strconv.Atoi(spec)
			if version < 4 || node.Type != "NodeTableCell" || context != "row" {
				return fmt.Errorf("invalid table cell rich text document spec [%s]", spec)
			}
			var fields map[string]json.RawMessage
			if err := json.Unmarshal(node.TableCellRich, &fields); nil != err || len(fields) != 3 {
				return fmt.Errorf("invalid table cell rich text payload")
			}
			for _, name := range []string{"spec", "format", "content"} {
				if len(fields[name]) == 0 || bytes.Equal(bytes.TrimSpace(fields[name]), []byte("null")) {
					return fmt.Errorf("missing table cell rich text field [%s]", name)
				}
			}
			var rich ast.TableCellRich
			if err := json.Unmarshal(node.TableCellRich, &rich); nil != err {
				return err
			}
			if _, err := av.ParseTableCellRich(&rich); nil != err {
				return err
			}
		}
		childContext := ""
		switch node.Type {
		case "NodeTable":
			childContext = "table"
		case "NodeTableHead":
			if context == "table" {
				childContext = "head"
			}

View on GitHub (pinned to 9f775e8a12)