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

  1. Filter out null/undefined entries from srcs before sending the request
  2. Fix the payload-building loop so every index holds a valid object ({id, isDetached, ...})
  3. 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

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


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.Tree

View on GitHub (pinned to 9f775e8a12)