{"record":{"id":"72396284a9459848","repo":"siyuan-note/siyuan","slug":"modes-is-required-0-for-light-1-for-dark-0-1-for-both","errorCode":null,"errorMessage":"[modes] is required ([0] for light, [1] for dark, [0,1] for both)","messagePattern":"\\[modes\\] is required \\(\\[0\\] for light, \\[1\\] for dark, \\[0,1\\] for both\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/apicontract/setting_config.go","lineNumber":150,"sourceCode":"\t\t\treturn\n\t\t}\n\t\tr.Theme, r.AppearanceMode = strings.TrimSpace(r.Theme), strings.TrimSpace(r.AppearanceMode)\n\t\tr.Modes = make([]float64, 0, 2)\n\t\tif r.Theme == \"\" {\n\t\t\treturn\n\t\t}\n\t\tfor _, raw := range modes {\n\t\t\tvar value float64\n\t\t\tif bytes.Equal(raw, []byte(\"null\")) || json.Unmarshal(raw, &value) != nil {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tif mode := int(value); mode != 0 && mode != 1 {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tr.Modes = append(r.Modes, value)\n\t\t}\n\t\tif len(r.Modes) == 0 {\n\t\t\terr = errors.New(\"[modes] is required ([0] for light, [1] for dark, [0,1] for both)\")\n\t\t}\n\t\treturn\n\t}\n}\n","sourceCodeStart":132,"sourceCodeEnd":155,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/apicontract/setting_config.go#L132-L155","documentation":"The SetTheme request decoder collects theme modes (0=light, 1=dark) from the 'modes' array, discarding invalid entries. If no valid mode survives, it fails with this message because the theme cannot be set without at least one mode.","triggerScenarios":"Calling the SetTheme endpoint with modes missing, an empty array, an array of only invalid values (non-integers or integers other than 0/1), or entries in the wrong JSON type (strings \"0\",\"1\").","commonSituations":"Clients sending mode names ('light'/'dark') instead of numeric codes, sending an empty modes array to 'unset' theme, or theme switcher code building the array from bad config state.","solutions":["Send modes as [0], [1], or [0,1] in the request JSON","Map symbolic names to codes before sending (light->0, dark->1)","Ensure each entry is a JSON number, not a string","Check the array length is > 0 client-side"],"exampleFix":"// before\nbody: JSON.stringify({ modes: [] })\n// after\nbody: JSON.stringify({ modes: [0, 1] })","handlingStrategy":"validation","validationCode":"function validModes(modes: unknown[]): number[] {\n  const out = modes.filter((m): m is number => m === 0 || m === 1);\n  if (out.length === 0) throw new Error('modes must include 0 (light) and/or 1 (dark)');\n  return out;\n}","typeGuard":"function isThemeMode(v: unknown): v is 0 | 1 { return v === 0 || v === 1; }","tryCatchPattern":"try { await setTheme(modes); } catch (e) { if (String(e).includes('[modes] is required')) { fallbackModes = [0, 1]; retry(fallbackModes); } }","preventionTips":["Use numeric codes 0/1, never 'light'/'dark' strings","Default to [0,1] when unsure","Validate entries are numbers before sending","Keep a named constant map THEME_MODES = { light: 0, dark: 1 }"],"tags":["validation","enum","empty-array"],"backgroundTag":"missing-required-argument","analyzedSha":"9f775e8a12daef8255556097396f9b2739078892","analyzedAt":"2026-09-19T03:17:15.984Z","contentChangedAt":"2026-09-19T03:17:15.984Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}