siyuan-note/siyuan · error

invalid card layout [ ]

Error message

invalid card layout [%v]

What it means

setAttrViewCardLayout validates that the value is an integer corresponding to a valid av.CardLayout (layout.IsValid()); fractional values or integers that do not map to a defined layout are rejected. Card layout is an enum and must be one of the predefined variants.

Solutions

  1. Pass only values from the current av.CardLayout enum (verify with layout.IsValid() equivalent client-side).
  2. Math.floor/validate the number is an integer before sending.
  3. Sync plugin constants with the kernel's CardLayout definitions after upgrading.

Example fix

// before
setLayout(avID, 0b11); // bit flags not allowed
// after
const layout = CardLayout.List; // a single defined enum value
if (Number.isInteger(layout)) setLayout(avID, layout);
Defensive patterns

Strategy: validation

Validate before calling

const n = Number(value);
if (!Number.isInteger(n) || !CardLayoutValues.includes(n)) throw new RangeError('invalid card layout');

Type guard

const isCardLayout = (v: unknown): v is CardLayout => Number.isInteger(v) && CardLayoutValues.includes(v as CardLayout);

Try / catch

try { await setCardLayout(avID, value); } catch (e) { if (String(e).includes('invalid card layout')) { await setCardLayout(avID, CardLayout.Table); } else throw e; }

Prevention

When it happens

Trigger: Sending a setAttrViewCardLayout operation with a fractional number or an integer that is not a defined av.CardLayout value (e.g. 99, negative).

Common situations: Plugin guesses layout indices after the kernel added new layout variants; UI sends a bit-flag combination instead of a single enum; copy-pasted code using another enum's values.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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

Appendix: source

Thrown at kernel/model/attribute_view.go:1880

	err = av.SaveAttributeView(attrView)
	return
}

func (tx *Transaction) doSetAttrViewCardLayout(operation *Operation) (ret *TxErr) {
	if err := setAttrViewCardLayout(operation); nil != err {
		return &TxErr{code: TxErrHandleAttributeView, id: operation.AvID, msg: err.Error()}
	}
	return
}

func setAttrViewCardLayout(operation *Operation) (err error) {
	value, err := getAttrViewOperationNumber(operation)
	if nil != err {
		return
	}
	layout := av.CardLayout(value)
	if value != math.Trunc(value) || !layout.IsValid() {
		return fmt.Errorf("invalid card layout [%v]", value)
	}

	attrView, err := av.ParseAttributeView(operation.AvID)
	if err != nil {
		return
	}
	view, err := getAttrViewOperationView(attrView, operation)
	if err != nil {
		return
	}

	switch view.LayoutType {
	case av.LayoutTypeGallery:
		view.Gallery.CardLayout = layout
	case av.LayoutTypeKanban:
		view.Kanban.CardLayout = layout
	default:
		return av.ErrWrongLayoutType

View on GitHub (pinned to 9f775e8a12)