siyuan-note/siyuan · error

invalid width for attribute view column

Error message

invalid width for attribute view column [%s]

What it means

While building the width map inside setAttributeViewColsWidth, each value in the Data map must be a string (the CSS width). If any value is a number, boolean, or nested object, the assertion value.(string) fails and the error names the offending column ID.

Solutions

  1. Convert every width value to a string, including units (e.g. "200px")
  2. Locate the column named in the [%s] interpolation and fix that entry
  3. Validate the width object client-side before queuing the transaction

Example fix

// before
{"20240101xxxx": 200}
// after
{"20240101xxxx": "200px"}
Defensive patterns

Strategy: validation

Validate before calling

for (const [id, w] of Object.entries(widths)) {
  if (typeof w !== "string") throw new Error(`width for column ${id} must be a string, got ${typeof w}`);
}

Type guard

const isWidthEntry = (e: [string, unknown]): e is [string, string] => typeof e[1] === "string";

Try / catch

try { await setAttrViewColWidth(op); } catch (e) { const m = String(e).match(/invalid width for attribute view column \[(.+)\]/); if (m) { widths[m[1]] = String(widths[m[1]]) + "px"; } else throw e; }

Prevention

When it happens

Trigger: POSTing a setAttrViewColWidth operation where one entry is {"colId": 200} (number) instead of {"colId": "200px"}.

Common situations: Scripts computing widths numerically and forgetting to stringify; plugins copying widths from DOM px values as numbers; schema drift between client versions.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at kernel/model/attribute_view.go:6824

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
	}
	if av.LayoutTypeTable != view.LayoutType {
		return nil
	}
	for _, column := range view.Table.Columns {
		if width, found := widths[column.ID]; found {
			column.Width = av.FilterWidthValue(width)

View on GitHub (pinned to 9f775e8a12)