siyuan-note/siyuan · error

clone attribute view [%s] views failed

Error message

clone attribute view [%s] views failed

What it means

After cloning, copyTemplateAttributeView asserts the clone preserved every view. If len(source.Views) != len(target.Views) the clone silently dropped or duplicated views, so the copy is rejected. This protects the view-ID remapping loop that follows from index misalignment.

Source

Thrown at kernel/model/template.go:538

}

func resolveCopyTemplateAttributeView(node *ast.Node, attrView *av.AttributeView) *av.View {
	if viewID := strings.TrimSpace(node.IALAttr(av.NodeAttrView)); "" != viewID {
		if view := attrView.GetView(viewID); nil != view {
			return view
		}
	}
	view, _ := attrView.GetFirstView()
	return view
}

func copyTemplateAttributeView(source *av.AttributeView) (ret *templateAttributeViewCopy, err error) {
	target := source.Clone()
	if nil == target {
		return nil, fmt.Errorf("clone attribute view [%s] failed", source.ID)
	}
	if len(source.Views) != len(target.Views) {
		return nil, fmt.Errorf("clone attribute view [%s] views failed", source.ID)
	}
	copiedViewIDs := map[string]string{}
	for i, sourceView := range source.Views {
		if nil == sourceView || nil == target.Views[i] {
			return nil, fmt.Errorf("clone attribute view [%s] view failed", source.ID)
		}
		copiedViewIDs[sourceView.ID] = target.Views[i].ID
	}
	return &templateAttributeViewCopy{target: target, copiedViewIDs: copiedViewIDs}, nil
}

func prepareTemplateAttributeViews(tree *parse.Tree, preview bool) (plans map[*ast.Node]*templateAttributeViewPlan,
	copies []*templateAttributeViewCopy, err error) {
	plans = map[*ast.Node]*templateAttributeViewPlan{}
	referenceSources := map[string]*av.AttributeView{}
	copySources := map[string]*av.AttributeView{}
	copyBySourceID := map[string]*templateAttributeViewCopy{}
	boxID := templateAttributeViewBoxID(tree)

View on GitHub (pinned to 8641553a1f)

Solutions

  1. Verify the source attribute view's Views array is well-formed (no entries that Clone would drop) and re-save the database in the UI
  2. Update/align the av package version so Clone copies all views; check git history of av.AttributeView.Clone for behavior changes
  3. Retry the template render after rebuilding the attribute view index (Ctrl+F5 / reload)

Example fix

// before: source with a nil view entry that clone drops
src.Views = append(src.Views, nil)
ret, err := copyTemplateAttributeView(src)
// after: prune nil views before copying
src.Views = slices.DeleteFunc(src.Views, func(v *av.View) bool { return v == nil })
ret, err := copyTemplateAttributeView(src)
Defensive patterns

Strategy: validation

Validate before calling

if len(src.Views) == 0 { return errors.New("attribute view has no views") }
// clone then verify:
if tgt := src.Clone(); tgt != nil && len(tgt.Views) != len(src.Views) { return errors.New("clone mismatch") }

Try / catch

ret, err := copyTemplateAttributeView(src)
if err != nil {
    logging.LogErrorf("clone views mismatch for av %s: %v", src.ID, err)
    return err
}

Prevention

When it happens

Trigger: Rendering a template with a copy-mode database whose Clone() implementation returns a target with a different number of Views than the source (e.g. clone skipped nil/broken views).

Common situations: Attribute view produced by an older or newer version of the av package where Clone behavior changed; corrupted view list in the source .av data.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11). Data as JSON: /api/errors/f34d00fabc29065e. Report an issue: GitHub.