{"record":{"id":"25fd8da1e40305ce","repo":"siyuan-note/siyuan","slug":"unsupported-frontend-s","errorCode":null,"errorMessage":"unsupported frontend [%s]","messagePattern":"unsupported frontend \\[(.+?)\\]","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/boot_appearance.go","lineNumber":715,"sourceCode":"\tfor _, frontend := range candidates {\n\t\tif frontend == \"all\" && len(manifestFrontends) == 0 {\n\t\t\tfor _, normalized := range []string{\"desktop\", \"mobile\"} {\n\t\t\t\tif !seen[normalized] {\n\t\t\t\t\tseen[normalized] = true\n\t\t\t\t\tfrontends = append(frontends, normalized)\n\t\t\t\t}\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\t\tnormalized := \"\"\n\t\tswitch frontend {\n\t\tcase \"desktop\":\n\t\t\tnormalized = \"desktop\"\n\t\tcase \"mobile\":\n\t\t\tnormalized = \"mobile\"\n\t\tdefault:\n\t\t\tif len(manifestFrontends) > 0 {\n\t\t\t\treturn nil, fmt.Errorf(\"unsupported frontend [%s]\", frontend)\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\t\tif !seen[normalized] {\n\t\t\tseen[normalized] = true\n\t\t\tfrontends = append(frontends, normalized)\n\t\t}\n\t}\n\tif len(frontends) == 0 && len(manifestFrontends) == 0 && len(pluginFrontends) == 0 {\n\t\tfrontends = append(frontends, \"desktop\", \"mobile\")\n\t}\n\tif len(frontends) == 0 {\n\t\treturn nil, errors.New(\"no supported frontend\")\n\t}\n\treturn frontends, nil\n}\n\nfunc validateOptionalBootAppearanceColor(color string) error {","sourceCodeStart":697,"sourceCodeEnd":733,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/model/boot_appearance.go#L697-L733","documentation":"Thrown by normalizeBootAppearanceFrontends when the manifest declares a frontend value that is not \"desktop\" or \"mobile\" and the manifest frontends list is non-empty. Unknown frontends in an explicit list are treated as manifest errors rather than silently skipped.","triggerScenarios":"A manifest with \"frontends\": [\"desktop\", \"mobile\", \"browser\"] or a misspelled \"dekstop\"; loadBootAppearance and the frontends unit test hit this path.","commonSituations":"Authors inventing new frontend names, typos in desktop/mobile, or copying plugin frontends conventions from other systems.","solutions":["Use only \"desktop\" and/or \"mobile\" in the manifest frontends list.","Fix misspellings (e.g. \"dekstop\" -> \"desktop\").","Remove unsupported frontend entries if the package targets both platforms."],"exampleFix":"// before\n\"frontends\": [\"desktop\", \"browser\"]\n// after\n\"frontends\": [\"desktop\"]","handlingStrategy":"validation","validationCode":"function validFrontends(list) { return (list || []).every(f => f === \"desktop\" || f === \"mobile\"); }","typeGuard":"const isFrontend = (v) => v === \"desktop\" || v === \"mobile\";","tryCatchPattern":"try { await installBootAppearance(pkg); } catch (e) { if (String(e).includes(\"unsupported frontend\")) { /* remove/fix the frontend entry in manifest */ } else throw e; }","preventionTips":["Only declare desktop and/or mobile","Lint manifest frontends against the two-value enum","Watch for typos like 'dekstop'"],"tags":["validation","manifest","frontend"],"backgroundTag":"unsupported-enum-value","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"}