siyuan-note/siyuan · error
invalid view state data key
Error message
invalid view state data key
What it means
validateViewStateDataKey rejects a view-state data key that is empty/whitespace-only or longer than 2048 bytes. The kernel stores per-view state payloads keyed by data keys, and keys beyond these limits would bloat or break the storage format, so PatchViewState refuses the write before persisting anything.
Source
Thrown at kernel/model/view_state.go:220
return int64(len(keys) + 1)
}
if ret <= state.Updated {
ret = state.Updated + 1
}
}
return ret
}
func validateViewStateKey(key string) error {
if "" == strings.TrimSpace(key) || 1024 < len(key) {
return errors.New("invalid view state key")
}
return nil
}
func validateViewStateDataKey(key string) error {
if "" == strings.TrimSpace(key) || 2048 < len(key) {
return errors.New("invalid view state data key")
}
return nil
}
func pruneViewStates(views map[string]*ViewState) {
if len(views) <= maxViewStateCount {
return
}
keys := make([]string, 0, len(views))
for key := range views {
keys = append(keys, key)
}
sort.Slice(keys, func(i, j int) bool {
left, right := views[keys[i]], views[keys[j]]
if left.Updated == right.Updated {
return keys[i] < keys[j]
}View on GitHub (pinned to 8641553a1f)
Solutions
- Ensure the data key is non-empty and trimmed before calling the patch API.
- Shorten the key: hash long identifiers (e.g. SHA-256 hex) instead of embedding full paths/URLs, keeping it under 2048 characters.
- Log the failing key at the call site to identify which concatenation produced an empty or oversized value.
Example fix
// before
const key = `${docPath}/${blockId}/${extra}`;
await patchViewState(viewId, key, data);
// after
const key = [docPath, blockId, extra].filter(Boolean).join("/").slice(0, 2048);
if (!key.trim()) throw new Error("view state data key required");
await patchViewState(viewId, key, data); Defensive patterns
Strategy: validation
Validate before calling
function isValidViewStateDataKey(key) {
return typeof key === "string" && key.trim().length > 0 && key.length <= 2048;
}
if (!isValidViewStateDataKey(key)) throw new Error("refusing to patch view state: bad data key"); Type guard
const isViewStateDataKey = (v) => typeof v === "string" && v.trim() !== "" && v.length <= 2048;
Prevention
- Hash long identifiers (paths, URLs) into short keys before use.
- Filter out empty components when building composite keys.
- Assert key validity in a small helper used by all view-state writes.
When it happens
Trigger: Calling the view-state patch API (PatchViewState path) with a data key that is "" or all whitespace, or a string whose length exceeds 2048 characters.
Common situations: A plugin or frontend feature builds the data key by concatenating IDs/paths and accidentally produces an empty string when an ID is missing; or embeds a long document path/blob ID, URL, or serialized JSON that exceeds 2048 characters.
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
- view state patch contains too many entries
- view state patch is too large
- invalid view state key
- data?.msg || data?.message || window.siyuan.languages._kerne
- wrong layout type
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/d6a34e9686f2f49f.
Report an issue: GitHub.