siyuan-note/siyuan · error
invalid attribute view source
Error message
invalid attribute view source [%d]
What it means
During batch rebinding of attribute-view sources, each entry of the srcs array is checked before any write happens. A nil entry (or an entry that is not an object) aborts the whole batch with this error, reporting the offending index. Validation completes for all entries before any tree is modified.
Solutions
- Filter out null/undefined entries from srcs before sending the request
- Fix the payload-building loop so every index holds a valid object ({id, isDetached, ...})
- Log the reported index and inspect that element of the request body
Example fix
// before api.bindAttributeView(sources); // sources[2] === null // after const valid = sources.filter(Boolean); api.bindAttributeView(valid);
Defensive patterns
Strategy: validation
Validate before calling
const clean = (srcs ?? []).filter(s => s !== null && s !== undefined && typeof s === 'object');
if (clean.length !== srcs.length) console.warn('dropped null attribute-view source entries'); Type guard
function isValidSource(s) { return s !== null && s !== undefined && typeof s === 'object'; } Try / catch
try {
await api.bindAttributeViewSources(srcs);
} catch (e) {
if (/invalid attribute view source \[\d+\]$/.test(e.message)) {
const idx = +e.message.match(/\[(\d+)\]/)[1];
srcs = srcs.filter((_, i) => i !== idx);
} else { throw e; }
} Prevention
- Filter null/undefined from arrays before serializing request payloads
- Avoid building arrays with possible empty slots (use push/filter, not index assignment)
- Validate the full batch payload client-side before sending
When it happens
Trigger: Calling the batch bind/detach API with a srcs array containing a null element at position N — typically produced by serializing entries where undefined became null, or by building the array programmatically with a skipped item.
Common situations: A plugin constructs the payload with JSON.stringify where undefined entries collapse to null; an off-by-one loop appends an empty slot; a client passes raw JSON with null placeholders.
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
- at least one visible view is required
- attribute view custom color index
- attribute view custom color must not be null
- attribute view custom colors count exceeds the
- attribute view custom colors must not be empty
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/48597688ef55d7e6.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/model/attribute_view.go:6071
}
func addAttributeViewBlocks(tx *Transaction, srcs []map[string]any, avID, dbBlockID, viewID, groupID, previousItemID string, ignoreDefaultFill bool) (result *insertAttrViewBlockResult, err error) {
result = &insertAttrViewBlockResult{}
if 0 == len(srcs) {
return
}
slices.Reverse(srcs) // https://github.com/siyuan-note/siyuan/issues/11286
attrView, err := avParseView(avID, dbBlockID)
if err != nil {
return
}
// 整批校验完成后再写入,避免后续条目越界时已修改前面的绑定。
boundTrees := map[string]*parse.Tree{}
detachedSources := make([]bool, len(srcs))
for index, src := range srcs {
if nil == src {
return result, fmt.Errorf("invalid attribute view source [%d]", index)
}
// 绑定条目的序列化数据可能省略值为 false 的字段,撤销重放时按绑定状态读取。
isDetached, ok := src["isDetached"].(bool)
if !ok && nil != src["isDetached"] {
return result, fmt.Errorf("invalid attribute view source [%d]: isDetached must be a boolean", index)
}
detachedSources[index] = isDetached
if isDetached {
continue
}
id, ok := src["id"].(string)
if !ok {
return result, fmt.Errorf("invalid attribute view source [%d]: id must be a string", index)
}
if !ast.IsNodeIDPattern(id) {
continue
}
var tree *parse.TreeView on GitHub (pinned to 9f775e8a12)