{"record":{"id":"ed11dbb9f17f518f","repo":"siyuan-note/siyuan","slug":"invalid-sort-position-s","errorCode":null,"errorMessage":"invalid sort position [%s]","messagePattern":"invalid sort position \\[(.+?)\\]","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/file.go","lineNumber":1291,"sourceCode":"\ttransaction := &Transaction{DoOperations: []*Operation{{Action: \"create\", Data: tree}}}\n\tPerformTransactions(&[]*Transaction{transaction})\n}\n\nvar createDocLock = sync.Mutex{}\n\nfunc CreateDocByMd(boxID, p, title, md string, sorts []string, arg map[string]any) (tree *parse.Tree, err error) {\n\tcreateDocLock.Lock()\n\tdefer createDocLock.Unlock()\n\n\tbox, err := getOpenedBox(boxID)\n\tif nil != err {\n\t\treturn\n\t}\n\tsortTargetID, _ := arg[\"sortTargetID\"].(string)\n\tsortPosition, _ := arg[\"sortPosition\"].(string)\n\tif \"\" != sortTargetID {\n\t\tif \"before\" != sortPosition && \"after\" != sortPosition {\n\t\t\treturn nil, fmt.Errorf(\"invalid sort position [%s]\", sortPosition)\n\t\t}\n\t\ttarget := treenode.GetBlockTree(sortTargetID)\n\t\tif !isSortableDocument(target) || target.BoxID != boxID || path.Dir(target.Path) != path.Dir(p) {\n\t\t\treturn nil, fmt.Errorf(\"sort target document [%s] is not a sibling of the new document\", sortTargetID)\n\t\t}\n\t} else if \"\" != sortPosition {\n\t\treturn nil, errors.New(\"sort target ID is required when sort position is specified\")\n\t}\n\n\tluteEngine := util.NewLute()\n\tluteEngine.SetHTMLTag2TextMark(true)\n\tdom := luteEngine.Md2BlockDOM(md, false)\n\ttree, err = createDoc(box.ID, p, title, dom, false)\n\tif err != nil {\n\t\treturn\n\t}\n\n\tFlushTxQueue()","sourceCodeStart":1273,"sourceCodeEnd":1309,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/model/file.go#L1273-L1309","documentation":"CreateDocByMd supports placing a new document before/after an existing sibling. When a sortTargetID is supplied, sortPosition must be exactly \"before\" or \"after\"; any other value (including empty and casing variants) triggers fmt.Errorf(\"invalid sort position [%s]\").","triggerScenarios":"Calling CreateDocByMd (API /api/filetree/createDocWithMd) with arg[\"sortTargetID\"] set and arg[\"sortPosition\"] not equal to \"before\" or \"after\".","commonSituations":"Plugin passing localized or capitalized position strings ('Before', 'top'); API scripts omitting sortPosition while setting sortTargetID; typos like 'befor'.","solutions":["Pass sortPosition as exactly \"before\" or \"after\" (lowercase) whenever sortTargetID is set.","Omit both sortTargetID and sortPosition to append the document without positional placement.","Validate the position string client-side before calling the API."],"exampleFix":"// before\ncreateDocWithMd({notebook, path, markdown, sortTargetID: target, sortPosition: \"Before\"});\n// after\ncreateDocWithMd({notebook, path, markdown, sortTargetID: target, sortPosition: \"before\"});","handlingStrategy":"validation","validationCode":"if (sortTargetID && sortPosition !== \"before\" && sortPosition !== \"after\") {\n  throw new Error('sortPosition must be \"before\" or \"after\"');\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat sortPosition as a strict enum: only \"before\" and \"after\"","Omit sortTargetID/sortPosition entirely when no relative placement is needed","Never pass localized or capitalized position strings to the API"],"tags":["validation","document-creation","sort"],"backgroundTag":"invalid-enum-value","analyzedSha":"8641553a1f07374001902d3ce773285db1292b2d","analyzedAt":"2026-09-11T16:08:28.414Z","contentChangedAt":"2026-09-11T16:08:28.414Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}