{"record":{"id":"c1dc5b227b139a89","repo":"siyuan-note/siyuan","slug":"conf-language-142-c1dc5b","errorCode":null,"errorMessage":"Conf.Language(142)","messagePattern":"Conf\\.Language\\(142\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/storage.go","lineNumber":202,"sourceCode":"\tU                 bool `json:\"u\"`\n\tDocTitle          bool `json:\"docTitle\"`\n\tCodeBlock         bool `json:\"codeBlock\"`\n\tMathBlock         bool `json:\"mathBlock\"`\n\tHtmlBlock         bool `json:\"htmlBlock\"`\n}\n\nvar criteriaLock = sync.Mutex{}\n\nfunc GetCriteria() (ret []*Criterion) {\n\tcriteriaLock.Lock()\n\tdefer criteriaLock.Unlock()\n\tret, _ = getCriteria()\n\treturn\n}\n\nfunc SetCriterion(criterion *Criterion) (err error) {\n\tif \"\" == criterion.Name {\n\t\treturn errors.New(Conf.Language(142))\n\t}\n\n\tcriteriaLock.Lock()\n\tdefer criteriaLock.Unlock()\n\n\tcriteria, err := getCriteria()\n\tif err != nil {\n\t\treturn\n\t}\n\n\tupdate := false\n\tfor i, c := range criteria {\n\t\tif c.Name == criterion.Name {\n\t\t\tcriteria[i] = criterion\n\t\t\tupdate = true\n\t\t\tbreak\n\t\t}\n\t}","sourceCodeStart":184,"sourceCodeEnd":220,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/model/storage.go#L184-L220","documentation":"SetCriterion saves a search/query criterion (saved filter) into storage/Storage/criteria.json. It refuses to persist a criterion whose Name field is the empty string, returning localized message 142 to tell the user a name is required. Criterion names are used as the identity for update-vs-insert, so an unnamed criterion could never be retrieved or updated.","triggerScenarios":"Calling /api/storage/setCriterion (or model.SetCriterion) with a Criterion object whose Name is \"\" — e.g. the frontend saves a query without the user typing a name, or a plugin constructs a Criterion programmatically and leaves Name unset.","commonSituations":"User clicks 'Save criterion' in the search panel dialog without entering a name; automated scripts or plugins exporting/importing saved searches omitting the name field after a schema change.","solutions":["Populate criterion.Name with a non-empty string before calling SetCriterion.","In the UI, disable the save action or validate the name input is non-empty before submitting.","If Name came from a deserialized payload, check the field mapping so the name is not silently dropped."],"exampleFix":"// before\ncriterion := &model.Criterion{Name: \"\"}\nmodel.SetCriterion(criterion)\n// after\nif criterion.Name == \"\" {\n    criterion.Name = \"My saved search\"\n}\nmodel.SetCriterion(criterion)","handlingStrategy":"validation","validationCode":"function canSetCriterion(criterion) {\n  return typeof criterion?.Name === \"string\" && criterion.Name.trim().length > 0;\n}","typeGuard":"function hasName(c) { return typeof c?.Name === \"string\" && c.Name.trim() !== \"\"; }","tryCatchPattern":"try {\n  await fetchPost(\"/api/storage/setCriterion\", { criterion });\n} catch (e) {\n  // message 142: prompt the user to enter a criterion name\n  showMessage(\"Please enter a name for the criterion\");\n}","preventionTips":["Validate the name input in the save-criterion dialog before enabling the save button","Never construct Criterion objects without an explicit Name","Trim user-entered names and reject whitespace-only values"],"tags":["go","storage","validation","i18n"],"backgroundTag":"empty-required-field","analyzedSha":"8641553a1f07374001902d3ce773285db1292b2d","analyzedAt":"2026-09-11T16:08:28.414Z","contentChangedAt":"2026-09-11T16:08:28.414Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}