siyuan-note/siyuan · error
attribute view item [%s] not found
Error message
attribute view item [%s] not found
What it means
Before applying a card cover position, the kernel verifies that the row (attribute view item / block value) identified by operation.RowID exists in the parsed attribute view via GetBlockValue. This error means the row ID does not correspond to any existing row in that view.
Source
Thrown at kernel/model/attribute_view.go:2065
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 8641553a1f)
Solutions
- Re-fetch the attribute view and confirm the row ID still exists before sending the operation
- Refresh the frontend view state if the row was deleted by another session
- Verify AvID and RowID belong to the same attribute view
- Drop the pending operation if the card was removed — it cannot succeed on retry
Example fix
// before applyCoverPosition(avID, staleRowID, ...) // row already deleted // after const av = await fetchAttrView(avID); if (!av.blocks.some(b => b.id === rowID)) return refreshView(); applyCoverPosition(avID, rowID, ...)
Defensive patterns
Strategy: validation
Validate before calling
const rowExists = (av, rowID) => av.blocks.some(b => b.id === rowID); if (!rowExists(await fetchAttrView(avID), rowID)) return refreshView();
Type guard
const blockValue = attrView?.blocks?.find?.(b => b.id === rowID);
Try / catch
try {
await transaction(op);
} catch (e) {
if (String(e).includes("attribute view item")) {
await reloadAttributeView(avID); // row deleted concurrently
}
} Prevention
- Re-fetch the view before mutating rows
- Treat the error as a signal to refresh stale UI state
- Confirm RowID and AvID belong to the same view
- Expect concurrent deletions in multi-client setups
When it happens
Trigger: Calling doSetAttrViewCardCoverPosition with a RowID that was deleted, belongs to a different attribute view, or was never created; also when the AvID and RowID are mismatched after UI state went stale.
Common situations: Concurrent editing where another client deleted the card; stale kanban/gallery state after undo or sync; passing a block ID from a different document; plugin operating on cached row IDs.
Understand the failure class
Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.
Related errors
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/ca76b5907e0434d4.
Report an issue: GitHub.