siyuan-note/siyuan · error

encrypted attribute view snapshot is missing notebook…

Error message

encrypted attribute view snapshot is missing notebook context

What it means

decryptHistoricalAttributeView validates snapshot data before decryption. If the snapshot was located without a notebook (boxID is empty — the workspace-global storage/av path matched) but the file content is ciphertext, the kernel has no notebook key context to decrypt it with, so it fails with this error. Plaintext data is returned as-is; encrypted data always requires its owning notebook.

Solutions

  1. Locate the snapshot copy inside its notebook directory (historyDir/<boxID>/storage/av/<avID>.json) so the boxID is available for decryption.
  2. Regenerate a history snapshot from the encrypted notebook so the AV file is stored with notebook context.
  3. If the data is genuinely not sensitive, re-save the attribute view so the snapshot is written unencrypted only if that matches your notebook encryption policy (normally not).
  4. Do not hand-edit or re-encrypt history files; use the documented recovery path in docs/ENCRYPTED-NOTEBOOK.md.
Defensive patterns

Strategy: try-catch

Try / catch

try {
  await renderHistoryAttributeView(avID, created);
} catch (e) {
  if (String(e.msg).includes("missing notebook context")) {
    // retry with the snapshot copy stored under its notebook directory (boxID available)
  }
}

Prevention

When it happens

Trigger: A history snapshot contains an encrypted attribute view file at the global path historyDir/storage/av/<avID>.json (no boxID derivable) while the source notebook had encryption enabled. This happens when a database belonging to an encrypted notebook was indexed/stored globally instead of inside its notebook directory.

Common situations: Encrypted-notebook users inspecting history of a database that was moved to the workspace level; snapshots produced by a version that misplaced encrypted AV data in the global storage path; corrupted or re-parented history trees after manual data directory manipulation.

Related errors


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

Appendix: source

Thrown at kernel/model/attribute_view_render.go:1492

	if err = gulu.JSON.UnmarshalJSON(data, attrView); err != nil {
		logging.LogErrorf("unmarshal attribute view [%s] failed: %s", avID, err)
		return
	}
	if err = av.CheckSpec(attrView); nil != err {
		return
	}
	attrView.CustomColorRenderContext = newHistoryAttributeViewCustomColorRenderContext(source.historyDir)
	attrView.ResolveDirectColors()

	viewable, err = renderAttributeView(attrView, "", viewID, carrierViewID, query, page, pageSize, groupPaging, false, false, nil, "")
	return
}

func decryptHistoricalAttributeView(boxID, avID string, data []byte) ([]byte, error) {
	ciphertext := util.IsCiphertext(data)
	if boxID == "" {
		if ciphertext {
			return nil, errors.New("encrypted attribute view snapshot is missing notebook context")
		}
		return data, nil
	}
	if !IsEncryptedBox(boxID) {
		if ciphertext {
			return nil, fmt.Errorf("encrypted attribute view snapshot has no matching notebook [%s]", boxID)
		}
		return data, nil
	}
	if !ciphertext {
		return nil, fmt.Errorf("encrypted notebook attribute view snapshot is plaintext [%s]", boxID)
	}
	return av.DecryptAVData(boxID, avID, data)
}

View on GitHub (pinned to 9f775e8a12)