{"record":{"id":"2bad57dca05c7ede","repo":"siyuan-note/siyuan","slug":"invalid-appearance-mode-s","errorCode":null,"errorMessage":"invalid appearance mode: %s","messagePattern":"invalid appearance mode: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/appearance.go","lineNumber":114,"sourceCode":"\t\t\t\t\treturn fmt.Errorf(\"theme [%s] not exists or not available for dark mode\", theme)\n\t\t\t\t}\n\t\t\t\tConf.Appearance.ThemeDark = theme\n\t\t\t}\n\t\t}\n\t}\n\n\tif appearanceMode != \"\" {\n\t\tswitch appearanceMode {\n\t\tcase \"light\":\n\t\t\tConf.Appearance.ModeOS = false\n\t\t\tConf.Appearance.Mode = 0\n\t\tcase \"dark\":\n\t\t\tConf.Appearance.ModeOS = false\n\t\t\tConf.Appearance.Mode = 1\n\t\tcase \"system\":\n\t\t\tConf.Appearance.ModeOS = true\n\t\tdefault:\n\t\t\treturn fmt.Errorf(\"invalid appearance mode: %s\", appearanceMode)\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc containTheme(name string, themes []*conf.AppearanceTheme) bool {\n\tfor _, t := range themes {\n\t\tif t.Name == name {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\nfunc containIcon(name string, icons []*conf.AppearanceIcon) bool {\n\tfor _, i := range icons {\n\t\tif i.Name == name {\n\t\t\treturn true","sourceCodeStart":96,"sourceCodeEnd":132,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/model/appearance.go#L96-L132","documentation":"SetTheme accepts appearanceMode only as one of the literals \"light\", \"dark\", or \"system\" (empty string skips OS-mode handling). Any other string is rejected with this error and the appearance configuration is left unchanged.","triggerScenarios":"Calling the setAppearance API with appearanceMode set to something other than \"\", \"light\", \"dark\", or \"system\" (e.g. \"auto\", \"Light\", \"os\", or a numeric value as a string).","commonSituations":"Script or plugin passes an internal enum like \"auto\" or 2; case mismatch (\"Light\"); frontend upgrade sends a new value an older kernel does not know; hand-edited request body.","solutions":["Send exactly \"light\", \"dark\", or \"system\" (or omit/empty to leave the OS mode unchanged)","Fix case-sensitivity: lowercase the value before sending","Map your app's internal mode enum to the three accepted literals before calling","Align frontend and kernel versions so both understand the same appearanceMode values"],"exampleFix":"// before\nSetTheme(\"daylight\", []int{0}, \"auto\")\n// after\nSetTheme(\"daylight\", []int{0}, \"system\")","handlingStrategy":"validation","validationCode":"const allowed = [\"\", \"light\", \"dark\", \"system\"];\nif (!allowed.includes(appearanceMode)) throw new Error(`appearanceMode must be one of ${allowed.join(\"|\")}`);","typeGuard":"const isAppearanceMode = (v) => typeof v === \"string\" && [\"\", \"light\", \"dark\", \"system\"].includes(v);","tryCatchPattern":"try {\n  await setTheme(theme, modes, appearanceMode);\n} catch (e) {\n  if (String(e).includes(\"invalid appearance mode\")) {\n    // normalize your enum to \"light\"|\"dark\"|\"system\" and retry\n  }\n}","preventionTips":["Only send the exact lowercase literals \"light\", \"dark\", \"system\" (or empty to skip)","Map internal mode enums to the accepted literals at the call boundary","Add a unit test covering each accepted appearanceMode value","Keep frontend and kernel versions in sync so mode vocabularies match"],"tags":["appearance","theme","invalid-enum","api"],"backgroundTag":"invalid-enum-value","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"}