siyuan-note/siyuan · error
snapshot version is not a document
Error message
snapshot version is not a document
What it means
Returned by loadSnapshotDocVersion (history_diff.go:413) when the repo object resolved by fileID has a path that does not end in ".sy". The data repo stores many object types (assets, conf, metadata); only .sy entries are documents and only those can be diffed. The check mirrors loadHistoryDocVersion's .sy guard for the snapshot path.
Source
Thrown at kernel/model/history_diff.go:413
}
func loadSnapshotDocVersion(fileID string) (ret *loadedDocVersion, err error) {
if "" == fileID {
return nil, errors.New("snapshot file ID is required")
}
if 1 > len(Conf.Repo.Key) {
return nil, errors.New(Conf.Language(26))
}
repo, err := newRepository()
if err != nil {
return nil, err
}
file, err := repo.GetFile(fileID)
if err != nil {
return nil, err
}
if !strings.HasSuffix(strings.ToLower(file.Path), ".sy") {
return nil, errors.New("snapshot version is not a document")
}
repoPath := strings.TrimPrefix(file.Path, "/")
pathParts := strings.SplitN(repoPath, "/", 2)
data, err := repo.OpenFile(file)
if err != nil {
return nil, err
}
ciphertext := util.IsCiphertext(data)
if ciphertext {
if len(pathParts) < 2 || !ast.IsNodeIDPattern(pathParts[0]) || !IsEncryptedBox(pathParts[0]) {
return nil, errors.New("encrypted snapshot document is missing valid notebook context")
}
HoldBoxReadLock(pathParts[0])
defer ReleaseBoxReadLock(pathParts[0])
dek, unlockErr := GetDEKIfUnlocked(pathParts[0])
if unlockErr != nil {
return nil, errors.New(Conf.Language(314))
}View on GitHub (pinned to 251596fc0d)
Solutions
- Only offer snapshot entries that the kernel's snapshot-listing API marks as documents.
- Before calling loadSnapshotDocVersion, confirm the object path ends in .sy (the listing API already provides it).
- If a non-document object must be inspected, use the dedicated repo/asset APIs, not the diff endpoint.
Example fix
// before
ref := &DocVersionRef{Type: "snapshot", ID: anyRepoHash}
// after
if !strings.HasSuffix(strings.ToLower(file.Path), ".sy") {
return errors.New("snapshot version is not a document")
}
ref := &DocVersionRef{Type: "snapshot", ID: docHash} Defensive patterns
Strategy: validation
Validate before calling
if !strings.HasSuffix(strings.ToLower(file.Path), ".sy") {
return errors.New("snapshot version is not a document")
}
// safe to load snapshot doc version Type guard
// isSnapshotDoc reports whether a repo file path is a .sy document.
func isSnapshotDoc(p string) bool {
return strings.HasSuffix(strings.ToLower(p), ".sy")
} Prevention
- Only list repo objects the kernel marks as documents in the snapshot picker.
- Validate the .sy suffix before constructing a snapshot-type DocVersionRef.
- Use dedicated repo/asset APIs for non-document objects.
When it happens
Trigger: DiffDocVersions with a snapshot fileID that points to a non-document repo object (an asset, a .json config blob); a UI that lists all repo objects rather than only document snapshots; a hand-crafted fileID.
Common situations: Frontend bug that exposes raw repo object hashes instead of the curated snapshot list; a plugin enumerating repo objects; corrupted snapshot index that references the wrong hash.
Related errors
AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12).
Data as JSON: /api/errors/edb67d03a078a7f7.
Report an issue: GitHub.