{"record":{"id":"6d38e26b873b8e03","repo":"siyuan-note/siyuan","slug":"invalid-boot-appearance-selection","errorCode":null,"errorMessage":"invalid boot appearance selection","messagePattern":"invalid boot appearance selection","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"kernel/model/boot_appearance.go","lineNumber":292,"sourceCode":"\n\tappearanceDir := filepath.Join(pluginDir, bootAppearanceDirName, appearanceID)\n\tfilePath, contentType, err = validateBootAppearanceResource(pluginDir, appearanceDir, relativePath, \"\")\n\treturn\n}\n\nfunc loadBootAppearanceSelection() (ret BootAppearanceSelection, err error) {\n\tret = defaultBootAppearanceSelection()\n\tbootAppearanceConfLock.RLock()\n\tdefer bootAppearanceConfLock.RUnlock()\n\tdata, err := filelock.ReadFile(filepath.Join(util.ConfDir, bootAppearanceConfigName))\n\tif err != nil {\n\t\treturn ret, err\n\t}\n\tif err = gulu.JSON.UnmarshalJSON(data, &ret); err != nil {\n\t\treturn ret, err\n\t}\n\tif ret.SchemaVersion != bootAppearanceSchemaVersion || (ret.Provider == \"\") != (ret.Appearance == \"\") {\n\t\treturn defaultBootAppearanceSelection(), errors.New(\"invalid boot appearance selection\")\n\t}\n\tif ret.Provider != \"\" && (!bazaar.IsValidPackageName(ret.Provider) || !isValidBootAppearanceID(ret.Appearance)) {\n\t\treturn defaultBootAppearanceSelection(), errors.New(\"invalid boot appearance selection\")\n\t}\n\treturn\n}\n\nfunc defaultBootAppearanceSelection() BootAppearanceSelection {\n\treturn BootAppearanceSelection{SchemaVersion: bootAppearanceSchemaVersion}\n}\n\nfunc loadSelectedBootAppearance() (selection BootAppearanceSelection, appearance *BootAppearance, err error) {\n\tselection, err = loadBootAppearanceSelection()\n\tif err != nil || selection.Provider == \"\" {\n\t\treturn\n\t}\n\tappearance, err = getBootAppearanceByID(selection.Provider, selection.Appearance)\n\tif err != nil {","sourceCodeStart":274,"sourceCodeEnd":310,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/model/boot_appearance.go#L274-L310","documentation":"loadBootAppearanceSelection reads the persisted boot appearance selection JSON and rejects it when the schema version does not match the current bootAppearanceSchemaVersion or when provider and appearance are inconsistent (exactly one set). The stored file is discarded and the default selection is returned with this error, so a corrupt/legacy file never produces an invalid splash screen.","triggerScenarios":"Starting the kernel or resolving boot appearance assets when the selection file was written by an older version (schemaVersion mismatch); the file was hand-edited or corrupted so provider is set but appearance is empty (or vice versa); the file contains arbitrary JSON whose SchemaVersion field is zero.","commonSituations":"Upgrading SiYuan across a boot-appearance format change; manual editing or partial writes of the selection file; syncing config files between different versions.","solutions":["Delete the stored boot appearance selection file so the default selection is recreated on next load.","Re-save the selection via SetBootAppearance with the current kernel version so the file is written with the current schema version.","If hand-editing, set SchemaVersion to the current bootAppearanceSchemaVersion and keep provider/appearance both set or both empty.","Ignore the error if you only need a usable default: callers already fall back to defaultBootAppearanceSelection()."],"exampleFix":"// before\n// stale file: {\"schemaVersion\": 1, \"provider\": \"my-theme\", \"appearance\": \"\"}\n// after\nmodel.SetBootAppearance(\"my-theme\", \"dark-splash\") // rewrites file with current schema version","handlingStrategy":"fallback","validationCode":"const selectionOk = (s) => s.schemaVersion === CURRENT && (s.provider === '') === (s.appearance === '')","typeGuard":"function isValidSelection(s) { return s != null && s.schemaVersion === CURRENT && (s.provider === '') === (s.appearance === '') }","tryCatchPattern":"sel, err := model.loadBootAppearanceSelection(data)\nif err != nil {\n    sel = model.DefaultBootAppearanceSelection() // already the library fallback\n}","preventionTips":["Don't hand-edit the selection file; use SetBootAppearance","After version upgrades, re-save or clear the selection file","Keep provider/appearance fields always written together"],"tags":["boot-appearance","schema-version","config"],"backgroundTag":"schema-validation-failed","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"}