siyuan-note/siyuan · error

snapshot file ID is required

Error message

snapshot file ID is required

What it means

Returned by loadSnapshotDocVersion (history_diff.go:399) when the fileID argument is empty. Snapshots live in the data repo (dejavu) and are addressed by their repo object hash; an empty ID cannot resolve to any object. The guard runs before the repo-key check so callers get the most specific message.

Source

Thrown at kernel/model/history_diff.go:399

			large:    1024*1024 <= len(data),
			boxID:    boxID,
			history:  historyRoot,
		}, nil
	}
	return &loadedDocVersion{
		tree:    tree,
		title:   tree.Root.IALAttr("title"),
		rootID:  tree.Root.ID,
		raw:     data,
		large:   1024*1024 <= len(data),
		boxID:   boxID,
		history: historyRoot,
	}, nil
}

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)

View on GitHub (pinned to 251596fc0d)

Solutions

  1. Require a non-empty snapshot id at the API boundary via BindJsonArg("id", &id, true, true) when type=="snapshot".
  2. On the client, disable the diff button until a snapshot row is selected.
  3. Log the incoming request body when this fires to catch field-name mismatches (id vs snapshot).

Example fix

// before
ref := &DocVersionRef{Type: "snapshot"} // id missing

// after
if ref.Type == "snapshot" && ref.ID == "" {
    return errors.New("snapshot file ID is required")
}
ref := &DocVersionRef{Type: "snapshot", ID: fileHash}
Defensive patterns

Strategy: validation

Validate before calling

if ref.Type == docVersionSnapshot && ref.ID == "" {
    return errors.New("snapshot file ID is required")
}
// safe to load snapshot doc version

Type guard

// validSnapshotRef reports whether ref is a snapshot with a non-empty fileID.
func validSnapshotRef(ref *DocVersionRef) bool {
    return ref != nil && ref.Type == docVersionSnapshot && ref.ID != ""
}

Prevention

When it happens

Trigger: POST /api/history/diffDocVersions with {"type":"snapshot","id":""} or a missing id field; a frontend bug that clears the snapshot ID before submitting; a plugin that constructs the ref conditionally.

Common situations: Frontend state race where the snapshot list is still loading when the user clicks diff; a refactoring that renamed the JSON field without updating all callers.

Related errors


AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12). Data as JSON: /api/errors/38b3503d815727aa. Report an issue: GitHub.