{"record":{"id":"1199b3e50a28852b","repo":"siyuan-note/siyuan","slug":"view-s-not-found-in-attribute-view-s","errorCode":null,"errorMessage":"view [%s] not found in attribute view [%s]","messagePattern":"view \\[(.+?)\\] not found in attribute view \\[(.+?)\\]","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/attribute_view.go","lineNumber":1398,"sourceCode":"\t}\n\treturn\n}\n\nfunc SetDatabaseBlockVisibleViews(blockID, avID string, viewIDs []string) (err error) {\n\tif 1 > len(viewIDs) {\n\t\treturn errors.New(\"at least one visible view is required\")\n\t}\n\n\tattrView, err := av.ParseAttributeView(avID)\n\tif nil != err {\n\t\tlogging.LogErrorf(\"parse attribute view [%s] failed: %s\", avID, err)\n\t\treturn\n\t}\n\n\tvisible := map[string]bool{}\n\tfor _, viewID := range viewIDs {\n\t\tif nil == attrView.GetView(viewID) {\n\t\t\treturn fmt.Errorf(\"view [%s] not found in attribute view [%s]\", viewID, avID)\n\t\t}\n\t\tvisible[viewID] = true\n\t}\n\n\tvar normalized []string\n\tfor _, view := range attrView.Views {\n\t\tif visible[view.ID] {\n\t\t\tnormalized = append(normalized, view.ID)\n\t\t}\n\t}\n\tif 1 > len(normalized) {\n\t\treturn errors.New(\"at least one visible view is required\")\n\t}\n\n\tnode, tree, err := getNodeByBlockID(nil, blockID)\n\tif nil != err {\n\t\treturn\n\t}","sourceCodeStart":1380,"sourceCodeEnd":1416,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/model/attribute_view.go#L1380-L1416","documentation":"Every ID passed in viewIDs must reference an existing view in the attribute view; SetDatabaseBlockVisibleViews uses attrView.GetView(viewID) and rejects any unknown ID. This prevents writing stale or bogus view IDs into the block's visible-view attribute.","triggerScenarios":"Calling SetDatabaseBlockVisibleViews with a viewIDs entry that was deleted, belongs to a different attribute view, or was never created (typo / stale ID).","commonSituations":"Plugin caches view IDs and one view was deleted meanwhile; frontend and kernel state diverged after a sync or concurrent edit; passing a block ID instead of a view ID by mistake.","solutions":["Fetch the current views (GetAttributeView / attrView.Views) and filter viewIDs to existing IDs before calling.","If a view was deleted, remove its ID from the visible list instead of passing it.","Re-read the attribute view after sync to refresh cached view IDs in the caller."],"exampleFix":"// before\nsetVisibleViews(avID, cachedViewIds);\n// after\nconst existing = new Set(attrView.views.map(v => v.id));\nsetVisibleViews(avID, cachedViewIds.filter(id => existing.has(id)));","handlingStrategy":"validation","validationCode":"const existing = new Set(attrView.views.map(v => v.id));\nconst valid = viewIDs.filter(id => existing.has(id));\nif (valid.length !== viewIDs.length) throw new Error('unknown view id in request');","typeGuard":"const viewExists = (av: { views: { id: string }[] }, id: string): boolean => av.views.some(v => v.id === id);","tryCatchPattern":"try { await setVisibleViews(blockID, avID, viewIDs); } catch (e) { if (String(e).includes('not found in attribute view')) { await refreshAttrView(avID); } else throw e; }","preventionTips":["Derive view IDs from a freshly fetched attribute view, not from cache","Purge cached view IDs when a view is deleted","Distinguish view IDs from block IDs and field IDs"],"tags":["attribute-view","not-found","validation"],"backgroundTag":"entity-not-found","analyzedSha":"9f775e8a12daef8255556097396f9b2739078892","analyzedAt":"2026-09-19T03:17:15.984Z","contentChangedAt":"2026-09-19T03:17:15.984Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}