siyuan-note/siyuan · error
current document ID is invalid
Error message
current document ID is invalid
What it means
Returned by ResolveDocVersionBoxID (history_diff.go:122) when ref.Type == "current" but ref.ID fails ast.IsNodeIDPattern. SiYuan block/document IDs are fixed-format 20-character base36-ish tokens; any other shape cannot be looked up in the block tree. The guard prevents a pointless treenode.GetBlockTree lookup and catches malformed input early.
Source
Thrown at kernel/model/history_diff.go:122
start int
end int
storedRuns []string
signature string
}
type docDiffLCSBudget struct {
remaining int
}
// ResolveDocVersionBoxID 返回文档版本引用中明确记录的加密笔记本 ID。
func ResolveDocVersionBoxID(ref *DocVersionRef) (string, error) {
if ref == nil {
return "", errors.New("document version is required")
}
switch ref.Type {
case docVersionCurrent:
if !ast.IsNodeIDPattern(ref.ID) {
return "", errors.New("current document ID is invalid")
}
blockTree := treenode.GetBlockTree(ref.ID)
if blockTree == nil {
return "", ErrTreeNotFound
}
if IsEncryptedBox(blockTree.BoxID) {
return blockTree.BoxID, nil
}
return "", nil
case docVersionHistory:
absPath, err := validateHistoryPath(ref.Path)
if err != nil {
return "", err
}
boxID := ExtractBoxIDFromHistoryPath(absPath)
if IsEncryptedBox(boxID) {
return boxID, nil
}View on GitHub (pinned to 251596fc0d)
Solutions
- Validate the ID with ast.IsNodeIDPattern(ref.ID) at the API boundary and return a 400-style message before calling ResolveDocVersionBoxID.
- Confirm the ID is the document root ID (20 chars) and not a heading/paragraph child block ID or a timestamp.
- If the ID comes from a URL/clipboard, trim whitespace and verify len==20 and all chars are in the node-ID alphabet.
Example fix
// before
ref := &DocVersionRef{Type: "current", ID: userInput}
// after
if ref.Type == "current" && !ast.IsNodeIDPattern(ref.ID) {
return fmt.Errorf("current document ID is invalid")
}
ref := &DocVersionRef{Type: "current", ID: userInput} Defensive patterns
Strategy: validation
Validate before calling
if ref == nil || ref.Type != docVersionCurrent {
return // nothing to validate here
}
if !ast.IsNodeIDPattern(ref.ID) {
return fmt.Errorf("current document ID is invalid")
}
// safe to call ResolveDocVersionBoxID(ref) Type guard
// isValidCurrentDocRef reports whether ref is a current-type ref with a valid 20-char block ID.
func isValidCurrentDocRef(ref *DocVersionRef) bool {
return ref != nil && ref.Type == docVersionCurrent && ast.IsNodeIDPattern(ref.ID)
} Prevention
- Source document IDs only from treenode.GetBlockTree or the editor root block, never from typed text.
- Validate IDs at the API layer before constructing a DocVersionRef.
- Trim and length-check (20 chars) IDs from URLs/clipboards.
When it happens
Trigger: POST /api/history/diffDocVersions with {"type":"current","id":"<garbage>"} or an empty id; a plugin passing a rootID truncated or with whitespace; copy-paste of a 14-char timestamp ID instead of the 20-char block ID.
Common situations: UI passes a doc ID from a stale clipboard; a script concatenates IDs incorrectly; version mismatch where older 14-char IDs are fed to newer kernels.
Related errors
- document version is required
- task list item marker length should be 1
- task list item marker can not be [ or ]
- custom emoji file is too large
- custom emoji file must not be empty
AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12).
Data as JSON: /api/errors/0d8cb4f281843567.
Report an issue: GitHub.