siyuan-note/siyuan · error
cannot parse attribute view
Error message
cannot parse attribute view %s: %v
What it means
After JSON validation, scanViews parses the attribute-view definition with av.ParseAttributeViewByPath and requires the parsed view to be non-nil with an ID matching the filename. A parse failure, nil result, or ID mismatch means the definition's internal ID does not correspond to its storage filename, so the relinker stops to avoid relinking under the wrong identity.
Solutions
- Restore the original definition so the internal id matches the filename
- Rename the file back to <internal-id>.json so it matches the id field
- Use the app's duplicate-database feature instead of copying .json files manually
- Rebuild the AV from the notebook block if the definition is unrecoverable
Example fix
// before
// file: storage/av/20240101120000-abc123.json, content id: "20240101120000-xyz789"
// after
// rename file to match internal id
os.Rename("data/storage/av/20240101120000-abc123.json", "data/storage/av/20240101120000-xyz789.json") Defensive patterns
Strategy: validation
Validate before calling
// confirm the internal id matches the filename before relinking
var probe struct { ID string `json:"id"` }
json.Unmarshal(data, &probe)
if probe.ID != idFromFilename {
// rename the file to match the internal id, or restore the original
} Prevention
- Use the app's built-in duplicate feature instead of copying .json files
- Never rename storage/av files manually
- Keep kernel and client versions in sync to avoid schema drift
When it happens
Trigger: storage/av/<id>.json is valid JSON but has an invalid schema, or the "id" field inside differs from <id> (file renamed/copied under a different ID, e.g. duplicating an AV file manually).
Common situations: A user copied an AV .json file to a new ID to 'clone' a database without updating its internal id; schema drift after downgrading/upgrading versions; hand-edited definitions.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- encrypted attribute view in global storage
- invalid attribute view JSON
- [/api/av/batchSetAttributeViewBlockAttrs] parameter [rowID]…
- at least one visible view is required
- attribute view content is unavailable
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/89b5efd33e2ea549.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/model/asset_relink.go:324
}
data, err := filelock.ReadFile(abs)
if err != nil {
return err
}
if util.IsCiphertext(data) {
return fmt.Errorf("encrypted attribute view in global storage: %s", id)
}
if !json.Valid(data) {
return fmt.Errorf("invalid attribute view JSON: %s", id)
}
if !p.mayContainReferences(data) {
continue
}
p.parsedViews++
cache.RemoveAVData(id)
view, err := av.ParseAttributeViewByPath(abs)
if err != nil || view == nil || view.ID != id {
return fmt.Errorf("cannot parse attribute view %s: %v", id, err)
}
before := len(p.result.References)
if err = p.attributeView(view, apicontract.AssetReference{AvID: id, Path: "storage/av/" + entry.Name()}); err != nil {
return err
}
if len(p.result.References) > before {
p.files = append(p.files, &assetRelinkFile{path: abs, before: data, view: view, items: p.referenceItems(before)})
owners := []apicontract.AssetReference{}
for _, tree := range p.trees {
ast.Walk(tree.Root, func(n *ast.Node, entering bool) ast.WalkStatus {
if entering && n.Type == ast.NodeAttributeView && n.AttributeViewID == id {
owners = append(owners, apicontract.AssetReference{Notebook: tree.Box, RootID: tree.Root.ID, BlockID: n.ID})
}
return ast.WalkContinue
})
}
if len(owners) > 0 {
references := append([]apicontract.AssetReference(nil), p.result.References[before:]...)View on GitHub (pinned to 9f775e8a12)