siyuan-note/siyuan · error
provider and appearance must both be empty or non-empty
Error message
provider and appearance must both be empty or non-empty
What it means
SetBootAppearance requires the provider and appearanceID parameters to be consistent: both empty means 'reset to default appearance', both non-empty selects an appearance. Passing exactly one of them (an impossible half-selection) is rejected with this error before any validation or persistence happens.
Source
Thrown at kernel/model/boot_appearance.go:220
if err != nil {
return &BootAppearance{Enabled: false}
}
if selection.Provider == "" || selection.Appearance == "" {
return &BootAppearance{Enabled: false}
}
return appearance
}
// SetBootAppearance 校验并原子持久化启动页外观选择,两项均为空表示恢复默认。
func SetBootAppearance(provider, appearanceID string) (ret BootAppearanceSelection, err error) {
if util.ReadOnly {
return defaultBootAppearanceSelection(), errors.New("read-only mode")
}
provider = strings.TrimSpace(provider)
appearanceID = strings.TrimSpace(appearanceID)
ret = defaultBootAppearanceSelection()
if (provider == "") != (appearanceID == "") {
err = errors.New("provider and appearance must both be empty or non-empty")
return
}
if provider != "" {
if !bazaar.IsValidPackageName(provider) || !isValidBootAppearanceID(appearanceID) {
err = ErrBootAppearanceNotFound
return
}
if _, resolveErr := getBootAppearanceByID(provider, appearanceID); resolveErr != nil {
err = ErrBootAppearanceNotFound
return
}
ret.Provider, ret.Appearance = provider, appearanceID
}
data, err := gulu.JSON.MarshalIndentJSON(ret, "", "\t")
if err != nil {
return ret, err
}View on GitHub (pinned to 8641553a1f)
Solutions
- Pass both provider and appearanceID, or pass both as empty strings to reset to the default appearance.
- Fix API payloads to include both fields explicitly.
- Validate the pair client-side before the call: (provider == "") == (appearanceID == "").
- If only the appearance should change, look up the current provider first and send it together with the new id.
Example fix
// before
model.SetBootAppearance("my-theme", "") // half-selection
// after
if reset { provider, id = "", "" }
model.SetBootAppearance(provider, id) // both set or both empty Defensive patterns
Strategy: validation
Validate before calling
function isConsistentPair(provider, id) { return (provider === '') === (id === '') } Prevention
- Send provider and appearanceID as an explicit pair, both empty or both set
- In UIs, disable the confirm action until the pair is complete
- Never omit one field in JSON payloads; use explicit empty strings for reset
When it happens
Trigger: Calling SetBootAppearance("my-theme", "") or SetBootAppearance("", "dark-splash") — after trimming, exactly one argument is empty; API clients that omit one field in the JSON body so it defaults to empty string.
Common situations: Frontend form where only the provider dropdown was chosen but no appearance id; API scripts resetting only one half of the pair; JSON payloads with a missing key instead of an explicit empty string pair.
Related errors
- invalid layer fit [%s]
- invalid layer position [%s]
- data?.msg || data?.message || window.siyuan.languages._kerne
- wrong layout type
- filter nesting depth exceeds the maximum allowed
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/4b0b11e7a54ac8ef.
Report an issue: GitHub.