siyuan-note/siyuan · error

card cover asset field [%s] not found

Error message

card cover asset field [%s] not found

What it means

Thrown by setAttrViewCardCoverPosition when the cover source is 'asset:<keyID>' but the referenced key either does not exist in the AttributeView (GetKey returns an error/nil) or is not of type KeyTypeMAsset (multi-asset). Cover-from-asset requires a live asset field to pull images from.

Source

Thrown at kernel/model/attribute_view.go:1954

	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 {
		key, getErr := attrView.GetKey(keyID)
		if nil != getErr || nil == key || av.KeyTypeMAsset != key.Type {
			return fmt.Errorf("card cover asset field [%s] not found", keyID)
		}
	}

	attrView.SetCardCoverPosition(operation.RowID, data.Source, data.Position)
	err = av.SaveAttributeView(attrView)
	return
}

func AppendAttributeViewDetachedBlocksWithValues(avID string, blocksValues [][]*av.Value) (err error) {
	attrView, err := av.ParseAttributeView(avID)
	if err != nil {
		logging.LogErrorf("parse attribute view [%s] failed: %s", avID, err)
		return
	}

	now := util.CurrentTimeMillis()
	var blockIDs []string
	for _, blockValues := range blocksValues {

View on GitHub (pinned to 251596fc0d)

Solutions

  1. On the client, validate that the asset keyID still exists and is of type mAsset before issuing the cover-position operation (use the AV key list).
  2. If the field was deleted, first switch the view's cover source back to 'content' (or to another live asset field), then re-send the position operation.
  3. Add a cleanup step when deleting mAsset keys to reset any view CoverFrom referencing them.

Example fix

// before
op.Data = { source: `asset:${deletedKeyID}`, position }
// after
const keys = await getAttrViewKeys(avID)
const assetKey = keys.find(k => k.id === keyID && k.type === 'mAsset')
if (!assetKey) {
  // reset view cover to content first, then send position with source: 'content'
} else {
  op.Data = { source: `asset:${assetKey.id}`, position }
}
Defensive patterns

Strategy: validation

Validate before calling

const keyID = op.data.source.startsWith('asset:') ? op.data.source.slice(6) : ''
if (keyID) {
  const key = (await getAttrViewKeys(avID)).find(k => k.id === keyID)
  if (!key || key.type !== 'mAsset') { /* reset cover source before sending */ }
}

Prevention

When it happens

Trigger: The asset field used as the cover source was deleted or had its type changed (e.g. from mAsset to text); the CoverFromAssetKeyID points at a stale key ID; a corrupted AV where the keyID reference is dangling.

Common situations: User deletes the asset column whose images supplied the card cover; restoring an AV backup that lost a column; plugin/automation that removed keys without updating the view's cover config.

Related errors


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