siyuan-note/siyuan · error
invalid appearance ID
Error message
invalid appearance ID
What it means
loadBootAppearance rejects the appearance ID before touching disk because it fails isValidBootAppearanceID: it must match the boot appearance ID pattern and be at most 64 characters. The kernel only loads boot appearances whose directory/manifest ID conform to this safe-identifier format, which prevents path traversal and filesystem-incompatible names.
Source
Thrown at kernel/model/boot_appearance.go:377
if err != nil {
return
}
current := defaultBootAppearanceSelection()
if err = gulu.JSON.UnmarshalJSON(data, ¤t); err != nil || current != expected {
return
}
data, err = gulu.JSON.MarshalIndentJSON(defaultBootAppearanceSelection(), "", "\t")
if err != nil {
return
}
if err = filelock.WriteFile(configPath, data); err != nil {
logging.LogWarnf("clear invalid boot appearance selection failed: %s", err)
}
}
func loadBootAppearance(pluginDir string, pkg *bazaar.Package, appearanceID string) (ret *BootAppearance, err error) {
if !isValidBootAppearanceID(appearanceID) {
err = errors.New("invalid appearance ID")
return
}
appearanceDir := filepath.Join(pluginDir, bootAppearanceDirName, appearanceID)
if err = validateBootAppearancePackage(pluginDir, appearanceDir); err != nil {
return
}
manifestPath, _, resolveErr := validateBootAppearanceResource(pluginDir, appearanceDir, bootAppearanceManifestName, "manifest")
if resolveErr != nil {
err = resolveErr
return
}
data, readErr := filelock.ReadFile(manifestPath)
if readErr != nil {
err = readErr
return
}
manifest := &bootAppearanceManifest{}
if err = gulu.JSON.UnmarshalJSON(data, manifest); err != nil {View on GitHub (pinned to 8641553a1f)
Solutions
- Rename the appearance directory under data/plugins/<provider>/appearances/ (or the plugin's boot appearance folder) so the ID matches the allowed pattern and is <= 64 characters, e.g. 'my-boot-screen'
- Update the appearance's manifest.json so its ID field exactly matches the renamed directory name
- If a bad selection was persisted, delete or reset the boot appearance selection config so the kernel falls back to the default boot appearance
- Update the plugin's plugin.json bootAppearances list to reference the corrected ID
Example fix
// before (manifest.json)
{"id": "My Boot Screen v1.0!", ...}
// after
{"id": "my-boot-screen-v1", ...}
// directory renamed to match: appearances/my-boot-screen-v1/ Defensive patterns
Strategy: validation
Validate before calling
function isValidAppearanceID(id) {
return typeof id === "string" && id.length > 0 && id.length <= 64 && /^[a-z0-9][a-z0-9-]*$/.test(id);
}
// only request boot appearances whose ID passes isValidAppearanceID Type guard
const isAppearanceID = (v: unknown): v is string => typeof v === "string" && v.length <= 64 && /^[a-z0-9][a-z0-9-]*$/.test(v);
Prevention
- Always generate appearance IDs as lowercase slugs (letters, digits, hyphens)
- Keep IDs at or under 64 characters
- Derive the manifest id from the directory name programmatically so they can never diverge
- Never include spaces, punctuation, or non-ASCII in appearance folder names
When it happens
Trigger: GetBootAppearances or getBootAppearanceByID calling loadBootAppearance with an appearanceID containing characters outside the allowed pattern (spaces, slashes, backslashes, non-ASCII), an empty string, or an ID longer than 64 characters. In practice this comes from a persisted selection file or a manifest declaring a boot appearance whose ID violates the pattern.
Common situations: A plugin author names the appearance folder 'My Boot Screen! v1' instead of a slug like 'my-boot-screen'; a copied manifest keeps an old ID with trailing whitespace; a corrupted boot-appearance.json selection file yields a malformed ID (this is usually caught earlier and mapped to ErrBootAppearanceNotFound, but loadBootAppearance re-checks defensively).
Understand the failure class
Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.
Related errors
- invalid hidden builtin style ID [%s]
- Plugin ${pluginLabel} returned an invalid action
- Plugin ${pluginLabel} returned invalid input: ${targetValida
- invalid frontend capability ID: %s
- invalid agent permission mode
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/6adc41efed7036e9.
Report an issue: GitHub.