siyuan-note/siyuan · error

invalid attribute view JSON

Error message

invalid attribute view JSON: %s

What it means

Each storage/av/<id>.json file must be valid JSON. If json.Valid(data) fails, the definition is corrupted and the relink scan aborts — parsing or rewriting references in a malformed definition could destroy database data.

Solutions

  1. Restore the file from history/backup or from the synced source
  2. Check disk space and re-trigger an AV index/repair if the app offers one
  3. Delete the corrupt definition only if the AV is unused, then recreate the database block
  4. Validate the file with a JSON linter before restoring to confirm it parses

Example fix

// before
// data/storage/av/<id>.json: "{...truncated"
// after
cp("history/2026-01-02-150405-replace/storage/av/<id>.json", "data/storage/av/<id>.json")
Defensive patterns

Strategy: validation

Validate before calling

// validate every AV definition parses before relinking
for _, f := range avFiles {
	data, _ := os.ReadFile(f)
	if !json.Valid(data) {
		// restore from history/backup before relink
	}
}

Try / catch

// catch and recover
if err := plan.Scan(); err != nil {
	if strings.Contains(err.Error(), "invalid attribute view JSON") {
		// restore the named file from history, then retry
	}
	return err
}

Prevention

When it happens

Trigger: scanViews reads storage/av/<id>.json and the bytes are not valid JSON (truncated write, binary garbage, partial sync, manual edit).

Common situations: Disk full during a previous write left a truncated file; a text editor saved the file with BOM/encoding damage; a sync conflict merged two JSON files badly; the file was overwritten by non-JSON content.

Understand the failure class

Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19). Data as JSON: /api/errors/57b598814c8b698c. Report an issue: GitHub.

Appendix: source

Thrown at kernel/model/asset_relink.go:315

		if err = p.observe(abs); err != nil {
			return err
		}
		p.reportProgress(abs)
		if entry.Type()&os.ModeSymlink != 0 {
			return fmt.Errorf("symbolic attribute view is not supported: %s", id)
		}
		if err = validateRelinkStoragePath(abs); err != nil {
			return err
		}
		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 {

View on GitHub (pinned to 9f775e8a12)