siyuan-note/siyuan · error
invalid attribute view source
Error message
invalid attribute view source [%d]: isDetached must be a boolean
What it means
In the same batch validation, if an entry contains an isDetached key whose value is not a boolean (and not absent), the batch is rejected with this error. Serialized bindings may omit isDetached (treated as false), but an explicitly present non-boolean value — e.g. the string "false" or the number 0 — is invalid.
Solutions
- Coerce isDetached to a real boolean (Boolean(value) or === comparison) before sending
- Omit the key entirely when the value is false, matching the omission-tolerant format
- Fix the client serializer to preserve JSON boolean types
Example fix
// before
{ id: blockID, isDetached: "true" }
// after
{ id: blockID, isDetached: true } Defensive patterns
Strategy: validation
Validate before calling
if ('isDetached' in src && typeof src.isDetached !== 'boolean') {
throw new Error('isDetached must be boolean');
} Type guard
function hasBooleanIsDetached(s) {
return !('isDetached' in s) || typeof s.isDetached === 'boolean';
} Try / catch
try {
await api.bindSources(srcs);
} catch (e) {
if (/isDetached must be a boolean/.test(e.message)) {
srcs = srcs.map(s => ({ ...s, isDetached: Boolean(s.isDetached) }));
} else { throw e; }
} Prevention
- Coerce form/CLI string booleans to real booleans before API calls
- Omit isDetached when false — the format tolerates omission
- Enable strict JSON typing in your client serializer
When it happens
Trigger: Calling the batch bind API with srcs[i].isDetached set to a non-boolean such as "true", 1, or null-derived values from a loosely typed client.
Common situations: JavaScript clients sending stringified booleans from form inputs; payloads round-tripped through CSV/JSON where booleans became strings; hand-written API calls.
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/80ce821af9b08642.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/model/attribute_view.go:6076
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.Tree
if tx != nil {
tree, err = tx.loadTree(id)
} else {
tree, err = LoadTreeByBlockID(id)
}View on GitHub (pinned to 9f775e8a12)