siyuan-note/siyuan · error

attribute view item [%s] not found

Error message

attribute view item [%s] not found

What it means

Thrown by setAttrViewCardCoverPosition when operation.RowID has no corresponding block value in the AttributeView (attrView.GetBlockValue(RowID) returns nil). The row/item must exist before its card cover position can be set, because the position is keyed off the item ID.

Source

Thrown at kernel/model/attribute_view.go:1933

		return fmt.Errorf("invalid card cover source [%s]", data.Source)
	}
	if nil != data.Position {
		if "" == data.Position.Image || 32*1024 < len(data.Position.Image) {
			return errors.New("invalid card cover image")
		}
		if math.IsNaN(data.Position.X) || math.IsInf(data.Position.X, 0) ||
			math.IsNaN(data.Position.Y) || math.IsInf(data.Position.Y, 0) ||
			data.Position.X < 0 || 100 < data.Position.X || data.Position.Y < 0 || 100 < data.Position.Y {
			return fmt.Errorf("invalid card cover position [%v, %v]", data.Position.X, data.Position.Y)
		}
	}

	attrView, err := av.ParseAttributeView(operation.AvID)
	if nil != err {
		return
	}
	if nil == attrView.GetBlockValue(operation.RowID) {
		return fmt.Errorf("attribute view item [%s] not found", operation.RowID)
	}
	view, err := getAttrViewViewByBlockID(attrView, operation.BlockID)
	if nil != err {
		return
	}
	if av.LayoutTypeGallery != view.LayoutType && av.LayoutTypeKanban != view.LayoutType {
		return av.ErrWrongLayoutType
	}
	var source string
	if av.LayoutTypeGallery == view.LayoutType {
		source = av.CardCoverSource(view.Gallery.CoverFrom, view.Gallery.CoverFromAssetKeyID)
	} else {
		source = av.CardCoverSource(view.Kanban.CoverFrom, view.Kanban.CoverFromAssetKeyID)
	}
	if data.Source != source {
		return fmt.Errorf("card cover source [%s] does not match view [%s]", data.Source, view.ID)
	}
	if keyID := av.CardCoverSourceAssetKeyID(data.Source); "" != keyID {

View on GitHub (pinned to 251596fc0d)

Solutions

  1. Refresh the AttributeView rows on the client before allowing cover-position edits, so the RowID is guaranteed to exist.
  2. Verify operation.RowID is present in the current AV block values before enqueueing the transaction (call GetAttributeViewPrimaryKeyValues or equivalent).
  3. If the row was just added, await the transaction commit confirmation before issuing the cover-position operation.

Example fix

// before
transaction([{ action: 'setAttrViewCardCoverPosition', avID, rowID: staleRowID, ... }])
// after
const rows = await fetchAvRows(avID)
if (rows.some(r => r.id === rowID)) {
  transaction([{ action: 'setAttrViewCardCoverPosition', avID, rowID, ... }])
}
Defensive patterns

Strategy: validation

Validate before calling

const rows = await getAttrViewPrimaryKeyValues(avID)
const exists = rows.some(r => r.id === operation.rowID)
if (!exists) { /* row was deleted; do not send cover-position op */ }

Try / catch

try {
  await performTx([coverPosOp])
} catch (e) {
  if (/attribute view item \[.*\] not found/.test(String(e.message ?? e))) {
    refreshAttrViewRows(avID) // row is gone locally; resync
  } else { throw e }
}

Prevention

When it happens

Trigger: Calling the setAttrViewCardCoverPosition transaction after the row was deleted, before it was committed/flushed, or with a RowID that belongs to a different AttributeView. Also reached if the AV was synced from another device and the row ID was never migrated.

Common situations: Stale frontend state that still holds a row reference after a sync/delete; race where a cover-position save fires during row removal; copy-paste of a row ID across notebooks.

Related errors


AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12). Data as JSON: /api/errors/ca76b5907e0434d4. Report an issue: GitHub.