siyuan-note/siyuan · error

source row [ ] not found in attribute view [ ]

Error message

source row [%s] not found in attribute view [%s]

What it means

When copying a row, the source row's block value is fetched with blockKeyValues.GetValue(srcRowID). If no value exists for that row ID in the block key, the source row does not exist in this attribute view and this error is returned. It prevents duplicating a non-existent or already-deleted row.

Solutions

  1. Re-fetch the database rows and use a currently existing row ID as srcRowID.
  2. Confirm the srcRowID is the row's block ID within the same avID, not a block from elsewhere.
  3. Refresh/sync the view and retry; if the row was deleted intentionally, discard the duplicate action.

Example fix

// before
await duplicateRow(avID, "20240101-deleted-row");
// after
const rows = await getAttrViewRows(avID);
if (rows.some(r => r.id === srcRowID)) await duplicateRow(avID, srcRowID);
Defensive patterns

Strategy: validation

Validate before calling

const rows = await getAttrViewRows(avID);
if (!rows.some(r => r.id === srcRowID)) throw new Error(`source row ${srcRowID} missing from ${avID}`);

Try / catch

try { await duplicateRow(avID, srcRowID); } catch (e) { if (String(e).includes("source row") && String(e).includes("not found")) await refreshRowsAndNotifyUser(); else throw e; }

Prevention

When it happens

Trigger: Row-duplication operations invoked with a srcRowID that was deleted, belongs to another database, or was never a row of the given avID.

Common situations: Stale UI state after another client deleted the row; passing a document block ID rather than the database row ID; race conditions between sync and a local duplicate action.

Understand the failure class

Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19). Data as JSON: /api/errors/89707b7c9df575b3. Report an issue: GitHub.

Appendix: source

Thrown at kernel/model/attribute_view.go:2199

// DuplicateAttributeViewRow 创建源行的纯文本副本,复制除主键、Rollup、Created、Updated 外的所有字段值,
// 双向关联同步更新目标属性视图的反向关联列。新行 ID 由调用方(前端)生成并通过 newRowID 传入,
// 副本插入到 previousItemID(通常为最后选中的条目)之后。
func DuplicateAttributeViewRow(tx *Transaction, avID, previousItemID, srcRowID, newRowID string) (err error) {
	attrView, err := av.ParseAttributeView(avID)
	if err != nil {
		logging.LogErrorf("parse attribute view [%s] failed: %s", avID, err)
		return
	}

	blockKeyValues := attrView.GetBlockKeyValues()
	if nil == blockKeyValues {
		err = fmt.Errorf("attribute view [%s] has no block key", avID)
		return
	}

	srcBlockVal := blockKeyValues.GetValue(srcRowID)
	if nil == srcBlockVal {
		err = fmt.Errorf("source row [%s] not found in attribute view [%s]", srcRowID, avID)
		return
	}

	if "" == newRowID {
		newRowID = ast.NewNodeID()
	}

	now := util.CurrentTimeMillis()

	// 创建副本的主键值,强制为纯文本(非绑定块)
	blockContent := ""
	if nil != srcBlockVal.Block {
		blockContent = srcBlockVal.Block.Content
	}
	newBlockVal := &av.Value{
		ID:         ast.NewNodeID(),
		KeyID:      blockKeyValues.Key.ID,
		BlockID:    newRowID,

View on GitHub (pinned to 9f775e8a12)