siyuan-note/siyuan · error
invalid width for attribute view column [%s]
Error message
invalid width for attribute view column [%s]
What it means
Thrown by setAttributeViewColsWidth when an individual value in the widths map cannot be asserted to string. Even though the overall Data is a map, each width entry must be a string value; numbers, booleans, or objects are rejected.
Source
Thrown at kernel/model/attribute_view.go:6343
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 251596fc0d)
Solutions
- Coerce every width to a string on the client before constructing the operation (String(width) / width.toString()).
- Omit entries whose width is null/undefined instead of sending them.
- Add a unit test that the widths payload is always Record<string, string>.
Example fix
// before
op.Data = { col1: 200, col2: '120px' } // mixed numeric/string
// after
op.Data = Object.fromEntries(
Object.entries(widths).filter(([, w]) => w != null).map(([id, w]) => [id, String(w)])
) Defensive patterns
Strategy: type-guard
Validate before calling
for (const [id, w] of Object.entries(op.data)) {
if (typeof w !== 'string') op.data[id] = String(w) // coerce before sending
} Type guard
function widthsAreStrings(d: unknown): d is Record<string, string> {
return typeof d === 'object' && d !== null && !Array.isArray(d) && Object.values(d).every(v => typeof v === 'string')
} Prevention
- Coerce width values to string at the source (state setter).
- Omit null/undefined width entries rather than forwarding them.
When it happens
Trigger: The widths object contains a numeric value (e.g. 200 instead of "200"), null, or a nested object for one of the columns. Often a frontend serialization oversight where a number was not coerced to string.
Common situations: Client storing widths as numbers in state and forwarding them unconverted; a column whose width was never set and serializes as null.
Related errors
- invalid attribute view column widths
- invalid card aspect ratio preset [%v]
- invalid card aspect ratio [%v]
- at least one visible view is required
- view [%s] not found in attribute view [%s]
AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12).
Data as JSON: /api/errors/1783409bfd43d2f6.
Report an issue: GitHub.