siyuan-note/siyuan · error

invalid attribute view column widths

Error message

invalid attribute view column widths

What it means

Thrown by setAttributeViewColsWidth when operation.Data cannot be asserted to map[string]any. The column-width operation expects a JSON object mapping column ID -> width string; any other shape (array, number, string, nil) fails the type assertion immediately.

Source

Thrown at kernel/model/attribute_view.go:6337

		return
	}

	err = av.SaveAttributeView(attrView)
	return
}

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

func setAttributeViewColsWidth(operation *Operation) (err error) {
	widthData, ok := operation.Data.(map[string]any)
	if !ok {
		return fmt.Errorf("invalid attribute view column widths")
	}
	widths := map[string]string{}
	for id, value := range widthData {
		width, valueOK := value.(string)
		if !valueOK {
			return fmt.Errorf("invalid width for attribute view column [%s]", id)
		}
		widths[id] = width
	}

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

View on GitHub (pinned to 251596fc0d)

Solutions

  1. Ensure the operation Data is a JSON object { [columnID: string]: string } before sending the transaction.
  2. On the client, build the payload with Object.fromEntries rather than pushing into an array.
  3. If integrating via the HTTP API, validate the JSON shape against the Operation.Data contract before posting.

Example fix

// before
op.Data = [['col1', '200px'], ['col2', '120px']] // array of pairs
// after
op.Data = { col1: '200px', col2: '120px' } // plain object
Defensive patterns

Strategy: type-guard

Validate before calling

function isWidthMap(d) {
  return d != null && typeof d === 'object' && !Array.isArray(d) && Object.values(d).every(v => typeof v === 'string')
}
if (!isWidthMap(op.data)) { /* rebuild as object { [id]: string } */ }

Type guard

type WidthMap = Record<string, string>
function isWidthMap(v: unknown): v is WidthMap {
  if (typeof v !== 'object' || v === null || Array.isArray(v)) return false
  return Object.values(v).every(x => typeof x === 'string')
}

Prevention

When it happens

Trigger: A frontend or API caller sends the widths payload as the wrong JSON type (e.g. an array of pairs, a single number, or omits Data entirely). Also reached by an undo replay whose captured Data was serialized differently.

Common situations: Client-side serialization bug; version skew where an older client uses a different payload schema; a manually crafted HTTP request to the transaction endpoint with a malformed body.

Related errors


AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12). Data as JSON: /api/errors/e9d21e67b5521114. Report an issue: GitHub.