{"record":{"id":"f982e2a767e4f4d0","repo":"siyuan-note/siyuan","slug":"invalid-sort-conf-s-expected-an-object","errorCode":null,"errorMessage":"invalid sort conf [%s]: expected an object","messagePattern":"invalid sort conf \\[(.+?)\\]: expected an object","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"kernel/model/file.go","lineNumber":2452,"sourceCode":"\treturn title\n}\n\nfunc readSortConfMap(confPath string) (map[string]int, error) {\n\tif !filelock.IsExist(confPath) {\n\t\treturn map[string]int{}, nil\n\t}\n\tdata, err := filelock.ReadFile(confPath)\n\tif err != nil {\n\t\tlogging.LogErrorf(\"read sort conf [%s] failed: %s\", confPath, err)\n\t\treturn nil, err\n\t}\n\tret := map[string]int{}\n\tif err = gulu.JSON.UnmarshalJSON(data, &ret); err != nil {\n\t\tlogging.LogWarnf(\"unmarshal sort conf [%s] failed: %s\", confPath, err)\n\t\treturn nil, err\n\t}\n\tif ret == nil {\n\t\treturn nil, fmt.Errorf(\"invalid sort conf [%s]: expected an object\", confPath)\n\t}\n\treturn ret, nil\n}\n\nfunc writeSortConfMap(confPath string, fullSortIDs map[string]int) error {\n\tdata, err := gulu.JSON.MarshalJSON(fullSortIDs)\n\tif err != nil {\n\t\tlogging.LogErrorf(\"marshal sort conf [%s] failed: %s\", confPath, err)\n\t\treturn err\n\t}\n\tif err = filelock.WriteFile(confPath, data); err != nil {\n\t\tlogging.LogErrorf(\"write sort conf [%s] failed: %s\", confPath, err)\n\t\treturn err\n\t}\n\treturn nil\n}\n\ntype DocSortModeResult struct {","sourceCodeStart":2434,"sourceCodeEnd":2470,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/model/file.go#L2434-L2470","documentation":"readSortConfMap unmarshals the per-notebook sort configuration file (.siyuan/sort.json or similar) into map[string]int; if JSON decoding yields a nil map (e.g. the file contains 'null' or a non-object like an array/string), the kernel returns fmt.Errorf(\"invalid sort conf [%s]: expected an object\", confPath). The message embeds the offending config file path.","triggerScenarios":"Any operation that loads doc sort configuration (listing files in a notebook, SetDocSortMode, sort reads) after sort conf was written as null, corrupted, or replaced by a non-object JSON value on disk.","commonSituations":"Manual editing of the sort conf file; a crashed write leaving 'null'; sync tools merging the file into a JSON array; older versions writing a different shape that no longer unmarshals into map[string]int.","solutions":["Delete or fix the corrupted sort conf file (path is shown in the error) so the kernel regenerates it","Replace the file content with a valid JSON object, e.g. {\"20230801...\": 0}","Restore the file from a backup or via sync history","Re-sync the workspace if the corruption came from a conflicted sync merge"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"// validate the sort conf file content before the kernel reads it\nfunction isValidSortConf(raw) {\n  const v = JSON.parse(raw);\n  return v !== null && typeof v === 'object' && !Array.isArray(v);\n}","typeGuard":"function isSortConfObject(v) {\n  return typeof v === 'object' && v !== null && !Array.isArray(v) &&\n    Object.values(v).every(n => typeof n === 'number');\n}","tryCatchPattern":"try {\n  const conf = JSON.parse(fs.readFileSync(confPath, 'utf8'));\n  if (!isSortConfObject(conf)) fs.unlinkSync(confPath); // let kernel regenerate\n} catch (e) {\n  fs.unlinkSync(confPath);\n}","preventionTips":["Never hand-edit workspace JSON config files while the kernel is running","Back up the workspace before manual config edits","After a failed write or crash, check the file for 'null' before relisting docs"],"tags":["siyuan","kernel","sort-conf","json","corrupt-config"],"backgroundTag":"unexpected-response-shape","analyzedSha":"8641553a1f07374001902d3ce773285db1292b2d","analyzedAt":"2026-09-11T16:08:28.414Z","contentChangedAt":"2026-09-11T16:08:28.414Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}