siyuan-note/siyuan · error
invalid attribute view source
Error message
invalid attribute view source [%d]: id must be a string
What it means
For non-detached entries in the batch, the id field must be a string block ID. If src[i].id is missing, null, or of another type, the whole batch is rejected with this error. (A string ID that merely fails the node-ID pattern is skipped, not an error.)
Solutions
- Ensure every non-detached entry has id as a string (String(id) if needed)
- Skip detached entries — they must not carry/require an id — and validate the payload shape before sending
- Fix the data source so block IDs are not coerced to numbers
Example fix
// before
{ id: 12345, isDetached: false }
// after
{ id: "20240101120000-abcd123", isDetached: false } Defensive patterns
Strategy: validation
Validate before calling
if (!src.isDetached && typeof src.id !== 'string') {
throw new Error(`entry ${i}: id must be a string`);
} Type guard
function hasStringId(s) { return s.isDetached === true || typeof s.id === 'string'; } Try / catch
try {
await api.bindSources(srcs);
} catch (e) {
if (/id must be a string/.test(e.message)) {
srcs = srcs.map(s => s.isDetached ? s : { ...s, id: String(s.id) });
} else { throw e; }
} Prevention
- Keep block IDs as strings end-to-end; watch for numeric coercion from row keys
- Validate payload shape (detached vs bound entries) before sending
- Only include id on bound (non-detached) entries
When it happens
Trigger: Calling the batch bind API where a non-detached entry lacks a string id — e.g. {isDetached: false} with no id, or id as a number from a numeric row key.
Common situations: Clients building payloads from table rows where IDs were coerced to numbers; entries whose id was stripped by a partial serializer; mixing detached and bound entries with the wrong shape.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- date display format is only available for date fields
- invalid attribute view source
- invalid card field full row value
- new item template field
- must be a string
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/d6a59d71b8a80ff1.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/model/attribute_view.go:6084
// 整批校验完成后再写入,避免后续条目越界时已修改前面的绑定。
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.Tree
if tx != nil {
tree, err = tx.loadTree(id)
} else {
tree, err = LoadTreeByBlockID(id)
}
if err != nil {
return
}
if err = validateAttributeViewBinding(avID, tree); err != nil {
return
}
boundTrees[id] = tree
}View on GitHub (pinned to 9f775e8a12)