siyuan-note/siyuan · error
local storage value for key
Error message
local storage value for key [%s] must not be empty
What it means
SetLocalStorageVals validates every key/value pair before persisting to the kernel's local storage (localStorage.json in the workspace). If any value in the submitted map is nil, the whole operation aborts with this error and nothing is written, since a nil value would corrupt the stored JSON map semantics. It is a client-input validation guard on the /api/storage/setLocalStorageVals endpoint.
Solutions
- Inspect the keyVals payload and remove or replace every null value with a concrete value before calling the API
- On the caller side, filter entries: build the map only from keys whose value is non-nil/non-undefined
- If the key should be cleared, use the remove-local-storage API/omit the key instead of passing nil
Example fix
// before
fetchPost("/api/storage/setLocalStorageVals", {keyVals: {theme: undefinedVal}})
// after
if (undefinedVal != null) {
fetchPost("/api/storage/setLocalStorageVals", {keyVals: {theme: undefinedVal}})
} Defensive patterns
Strategy: validation
Validate before calling
function canSetLocalStorageVals(keyVals) {
return Object.entries(keyVals).every(([k, v]) => v != null);
}
if (!canSetLocalStorageVals(keyVals)) throw new Error("null value in keyVals"); Type guard
function hasNoNilValues(m map[string]any) bool {
for _, v := range m { if v == nil { return false } }
return true
} Prevention
- Filter out null/undefined entries before sending keyVals to the API
- Use remove-key APIs instead of null to clear a stored value
- In TypeScript, type payload values as NonNullable<T> to catch nulls at compile time
When it happens
Trigger: Calling kernel API /api/storage/setLocalStorageVals with a JSON payload where some key maps to null; frontend/plugin code doing localStorage setItem with an undefined-valued variable.
Common situations: A frontend reads an unset variable (undefined) and serializes it to null; a plugin builds the keyVals map programmatically and one optional field is missing; deserialized data lost a value.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- inline style must not be null
- all asset mappings failed
- assetPath is not an image referenced by the document
- assetPath is required for analyze
- at least one asset path or mapping is required
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/84a1a0b65752fdbe.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/model/storage.go:61
defer localStorageLock.Unlock()
return getLocalStorage()
}
func SetLocalStorage(val map[string]any) (err error) {
localStorageLock.Lock()
defer localStorageLock.Unlock()
return setLocalStorage(val)
}
func SetLocalStorageVals(keyVals map[string]any) (setKeyVals map[string]any, err error) {
localStorageLock.Lock()
defer localStorageLock.Unlock()
setKeyVals = make(map[string]any, len(keyVals))
localStorage := getLocalStorage()
for k, v := range keyVals {
if v == nil {
err = fmt.Errorf("local storage value for key [%s] must not be empty", k)
return
}
localStorage[k] = v
setKeyVals[k] = v
}
err = setLocalStorage(localStorage)
return
}
func RemoveLocalStorageVals(keys []string) (err error) {
localStorageLock.Lock()
defer localStorageLock.Unlock()
localStorage := getLocalStorage()
for _, key := range keys {
delete(localStorage, key)
}
return setLocalStorage(localStorage)View on GitHub (pinned to 9f775e8a12)