{"record":{"id":"3ef44b9cc8bc6325","repo":"siyuan-note/siyuan","slug":"clone-attribute-view-s-view-failed","errorCode":null,"errorMessage":"clone attribute view [%s] view failed","messagePattern":"clone attribute view \\[(.+?)\\] view failed","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/template.go","lineNumber":543,"sourceCode":"\t\t\treturn view\n\t\t}\n\t}\n\tview, _ := attrView.GetFirstView()\n\treturn view\n}\n\nfunc copyTemplateAttributeView(source *av.AttributeView) (ret *templateAttributeViewCopy, err error) {\n\ttarget := source.Clone()\n\tif nil == target {\n\t\treturn nil, fmt.Errorf(\"clone attribute view [%s] failed\", source.ID)\n\t}\n\tif len(source.Views) != len(target.Views) {\n\t\treturn nil, fmt.Errorf(\"clone attribute view [%s] views failed\", source.ID)\n\t}\n\tcopiedViewIDs := map[string]string{}\n\tfor i, sourceView := range source.Views {\n\t\tif nil == sourceView || nil == target.Views[i] {\n\t\t\treturn nil, fmt.Errorf(\"clone attribute view [%s] view failed\", source.ID)\n\t\t}\n\t\tcopiedViewIDs[sourceView.ID] = target.Views[i].ID\n\t}\n\treturn &templateAttributeViewCopy{target: target, copiedViewIDs: copiedViewIDs}, nil\n}\n\nfunc prepareTemplateAttributeViews(tree *parse.Tree, preview bool) (plans map[*ast.Node]*templateAttributeViewPlan,\n\tcopies []*templateAttributeViewCopy, err error) {\n\tplans = map[*ast.Node]*templateAttributeViewPlan{}\n\treferenceSources := map[string]*av.AttributeView{}\n\tcopySources := map[string]*av.AttributeView{}\n\tcopyBySourceID := map[string]*templateAttributeViewCopy{}\n\tboxID := templateAttributeViewBoxID(tree)\n\tast.Walk(tree.Root, func(n *ast.Node, entering bool) ast.WalkStatus {\n\t\tif !entering || ast.NodeAttributeView != n.Type {\n\t\t\treturn ast.WalkContinue\n\t\t}\n","sourceCodeStart":525,"sourceCodeEnd":561,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/model/template.go#L525-L561","documentation":"During per-view validation of a cloned attribute view, either the source view at index i or the corresponding cloned view is nil. The copy is aborted because the view cannot be remapped. This catches malformed individual views inside an otherwise size-matched Views slice.","triggerScenarios":"Rendering a template with a copy-mode database where source.Views[i] is a nil entry or the clone produced a nil view at the same index.","commonSituations":"Hand-edited or partially written .av data containing null view entries; a clone bug that leaves holes in the slice.","solutions":["Remove null entries from the attribute view's Views array (fix the .av JSON or re-create the view in the UI)","Rebuild/re-save the database so the kernel serializes a clean view list, then retry","Ensure no code path inserts nil views into AttributeView.Views"],"exampleFix":"// before: .av JSON Views array containing null entries\n// after: reopen and re-save the database in the UI, or strip nulls:\nviews := make([]*av.View, 0, len(src.Views))\nfor _, v := range src.Views { if v != nil { views = append(views, v) } }\nsrc.Views = views","handlingStrategy":"validation","validationCode":"for i, v := range src.Views { if v == nil { return fmt.Errorf(\"nil view at index %d\", i) } }","typeGuard":"func hasNilView(src *av.AttributeView) bool {\n    for _, v := range src.Views { if v == nil { return true } }\n    return false\n}","tryCatchPattern":"ret, err := copyTemplateAttributeView(src)\nif err != nil { return fmt.Errorf(\"template database copy failed: %w\", err) }","preventionTips":["Strip null entries from Views before serializing .av files","Never append nil views programmatically","Validate .av JSON after external edits"],"tags":["go","attribute-view","null-value","internal"],"backgroundTag":"internal-invariant-violation","analyzedSha":"8641553a1f07374001902d3ce773285db1292b2d","analyzedAt":"2026-09-11T16:08:28.414Z","contentChangedAt":"2026-09-11T16:08:28.414Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}