siyuan-note/siyuan · error
source IDs must not be empty
Error message
source IDs must not be empty
What it means
ReorderDocs / ReorderDocTree validate their inputs through validateReorderArgs before touching any files. This error means the sourceIDs slice passed to the reorder operation was empty (nil or zero length). The reorder operation is defined only as 'move these one or more sibling docs before/after a target doc', so an empty source list is meaningless and rejected immediately.
Source
Thrown at kernel/model/file.go:2719
}
maps.Copy(fullSortIDs, sortIDs)
if writeErr := writeSortConfMap(confPath, fullSortIDs); nil != writeErr {
fileTreeSortLock.Unlock()
return ret, writeErr
}
fileTreeSortLock.Unlock()
ret.Changed = true
ret.Notebook = box.ID
ret.ParentPath = parentPath
IncSync()
pushFiletreeSortChanged(sortIDs)
return
}
func validateReorderArgs(sourceIDs []string, targetID, position string) error {
if 1 > len(sourceIDs) {
return errors.New("source IDs must not be empty")
}
if "before" != position && "after" != position {
return fmt.Errorf("invalid reorder position [%s]", position)
}
seen := map[string]struct{}{}
for _, sourceID := range sourceIDs {
if sourceID == targetID {
return fmt.Errorf("target ID [%s] must not be included in source IDs", targetID)
}
if _, ok := seen[sourceID]; ok {
return fmt.Errorf("duplicate source ID [%s]", sourceID)
}
seen[sourceID] = struct{}{}
}
return nil
}
func isSortableDocument(tree *treenode.BlockTree) bool {View on GitHub (pinned to 8641553a1f)
Solutions
- Ensure the sources/sourceIDs array contains at least one document ID before calling ReorderDocs/ReorderDocTree
- Guard the caller: return early or no-op when the selection is empty instead of issuing the API call
- Check the frontend/plugin drag pipeline for losing the selection data before the request is sent
Example fix
// before
result, err := model.ReorderDocs(sourceIDs, targetID, "before")
// after
if len(sourceIDs) == 0 {
return nil // nothing to reorder; skip the call
}
result, err := model.ReorderDocs(sourceIDs, targetID, "before") Defensive patterns
Strategy: validation
Validate before calling
if len(sourceIDs) == 0 {
return errors.New("reorder requires at least one source document ID")
} Type guard
func hasSources(sourceIDs []string) bool { return len(sourceIDs) > 0 } Try / catch
if err := validateSources(sourceIDs); err != nil {
// handle locally; do not call ReorderDocs
return err
} Prevention
- Always derive sourceIDs from a checked non-empty selection before the API call
- No-op early when nothing is selected in drag/selection handlers
- Add a caller-side assertion or unit test for empty-input rejection
When it happens
Trigger: Calling the kernel API ReorderDocs([]string{}, "target-id", "before") / ReorderDocTree with an empty sources array; a frontend drag handler that computes the dragged block IDs after the DOM data was already cleared; mapping an empty selection into the API call.
Common situations: Plugin or client code building the request from a multi-select that was empty; a race where documents were removed from selection before the reorder request fired; scripts automating SiYuan that pass an unpopulated array variable.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- target ID [%s] must not be included in source IDs
- duplicate source ID [%s]
- wrong layout type
- filter nesting depth exceeds the maximum allowed
- invalid session id
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/9ce35f119265810e.
Report an issue: GitHub.