siyuan-note/siyuan · error
sort target ID is required when sort position is specified
Error message
sort target ID is required when sort position is specified
What it means
CreateDocByMd in kernel/model/file.go:1298 lets callers position a new document relative to an existing sibling document. The sort target ID (sortTargetID) and the sort position (sortPosition) are a paired argument set: a position is meaningless without the reference document it is relative to. When a sortPosition is supplied but sortTargetID is empty, the function rejects the request instead of guessing a placement.
Source
Thrown at kernel/model/file.go:1298
createDocLock.Lock()
defer createDocLock.Unlock()
box, err := getOpenedBox(boxID)
if nil != err {
return
}
sortTargetID, _ := arg["sortTargetID"].(string)
sortPosition, _ := arg["sortPosition"].(string)
if "" != sortTargetID {
if "before" != sortPosition && "after" != sortPosition {
return nil, fmt.Errorf("invalid sort position [%s]", sortPosition)
}
target := treenode.GetBlockTree(sortTargetID)
if !isSortableDocument(target) || target.BoxID != boxID || path.Dir(target.Path) != path.Dir(p) {
return nil, fmt.Errorf("sort target document [%s] is not a sibling of the new document", sortTargetID)
}
} else if "" != sortPosition {
return nil, errors.New("sort target ID is required when sort position is specified")
}
luteEngine := util.NewLute()
luteEngine.SetHTMLTag2TextMark(true)
dom := luteEngine.Md2BlockDOM(md, false)
tree, err = createDoc(box.ID, p, title, dom, false)
if err != nil {
return
}
FlushTxQueue()
if "" != sortTargetID {
if _, sortErr := ReorderDocs([]string{tree.ID}, sortTargetID, sortPosition); nil != sortErr {
logging.LogErrorf("reorder created document [%s] failed: %s", tree.ID, sortErr)
box.setSortByConf(path.Dir(tree.Path), tree.ID)
}
} else if 0 < len(sorts) {
ChangeFileTreeSort(box.ID, sorts)View on GitHub (pinned to 8641553a1f)
Solutions
- Pass the ID of the sibling document the new doc should be placed relative to (sortTargetID) together with sortPosition.
- If you do not need positional placement, omit sortPosition entirely and pass the parent path (hPath/parentID) instead.
- Verify the target ID is a valid, sortable sibling document in the same notebook and same parent path (the next validation after this one checks isSortableDocument, BoxID, and sibling dir).
Example fix
// before
createDocByMd(boxID, hPath, md, {sortPosition: "after"});
// after
createDocByMd(boxID, hPath, md, {sortPosition: "after", sortTargetID: "20240101120000-abcdefg"}); Defensive patterns
Strategy: validation
Validate before calling
if (sortPosition && !sortTargetID) {
throw new Error("sortTargetID is required when sortPosition is set");
}
const target = await getBlockTreeByID(sortTargetID); // must exist, be sortable, same notebook & parent dir Type guard
function hasValidSortTarget(args) {
return !args.sortPosition || (typeof args.sortTargetID === "string" && args.sortTargetID.length > 0);
} Try / catch
try {
await createDocByMd(boxID, hPath, md, {sortPosition, sortTargetID});
} catch (e) {
if (String(e.msg).includes("sort target ID is required")) {
await createDocByMd(boxID, hPath, md, {}); // fall back to default placement
} else { throw e; }
} Prevention
- Treat sortTargetID and sortPosition as an atomic pair; never send one without the other.
- Derive sortTargetID from the actual DOM/tree node that the user dropped onto.
- Add a payload schema check in client code before issuing the API call.
When it happens
Trigger: Calling CreateDocByMd (or the /api/filetree/createDocWithMdByPosition-style endpoints that wrap it) with a non-empty sortPosition (e.g. 'before', 'after', or an index) while leaving the sortTargetID/sortTarget argument empty string.
Common situations: Plugin or automation scripts that build the request payload programmatically and include sortPosition copied from a template but never set the target ID; frontends that compute position from a drag-drop but lose the dragged-over document's ID; API consumers porting code from an older SiYuan version where position could be specified standalone.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- parent ID is required
- previous ID and next ID cannot both be specified
- invalid skill name: %s
- wrong layout type
- filter nesting depth exceeds the maximum allowed
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/7f6f597307af00ca.
Report an issue: GitHub.