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

  1. Only offer snapshot entries that the kernel's snapshot-listing API marks as documents.
  2. Before calling loadSnapshotDocVersion, confirm the object path ends in .sy (the listing API already provides it).
  3. 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

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.