{"record":{"id":"fa6238da426ac78d","repo":"siyuan-note/siyuan","slug":"invalid-view-state-key","errorCode":null,"errorMessage":"invalid view state key","messagePattern":"invalid view state key","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/view_state.go","lineNumber":213,"sourceCode":"\t\t\t\t\treturn keys[i] < keys[j]\n\t\t\t\t}\n\t\t\t\treturn left.Updated < right.Updated\n\t\t\t})\n\t\t\tfor i, key := range keys {\n\t\t\t\tviews[key].Updated = int64(i + 1)\n\t\t\t}\n\t\t\treturn int64(len(keys) + 1)\n\t\t}\n\t\tif ret <= state.Updated {\n\t\t\tret = state.Updated + 1\n\t\t}\n\t}\n\treturn ret\n}\n\nfunc validateViewStateKey(key string) error {\n\tif \"\" == strings.TrimSpace(key) || 1024 < len(key) {\n\t\treturn errors.New(\"invalid view state key\")\n\t}\n\treturn nil\n}\n\nfunc validateViewStateDataKey(key string) error {\n\tif \"\" == strings.TrimSpace(key) || 2048 < len(key) {\n\t\treturn errors.New(\"invalid view state data key\")\n\t}\n\treturn nil\n}\n\nfunc pruneViewStates(views map[string]*ViewState) {\n\tif len(views) <= maxViewStateCount {\n\t\treturn\n\t}\n\n\tkeys := make([]string, 0, len(views))\n\tfor key := range views {","sourceCodeStart":195,"sourceCodeEnd":231,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/model/view_state.go#L195-L231","documentation":"validateViewStateKey requires a view-state key to be non-blank and at most 1024 bytes. Keys that are empty, whitespace-only, or longer than 1024 characters make GetViewState, PatchViewState, and RemoveViewState fail with this error.","triggerScenarios":"GetViewState(key), PatchViewState(key, ...), or RemoveViewState(key) called with key == \"\", a whitespace-only string (e.g. \" \"), or a string longer than 1024 bytes (e.g. a concatenated document ID + block ID + plugin name that grew too long).","commonSituations":"An unset variable or empty request parameter reaching the API before validation; building keys from optional components where all components are missing; prefix-style keys that embed long paths, URLs, or IDs and exceed the length cap.","solutions":["Ensure the key is non-empty before calling — validate/derive a fallback key at the call site","Shorten the key: use a fixed short namespace plus a hash (e.g. SHA-256 hex, 64 chars) of the long composite instead of the raw concatenation","Check the frontend/API layer so an empty or whitespace key is rejected or defaulted before the request is sent"],"exampleFix":"// before\nkey := docID + \"/\" + blockID + \"/\" + longContext\nmodel.PatchViewState(key, values, nil)\n// after\nsum := sha256.Sum256([]byte(docID + \"/\" + blockID + \"/\" + longContext))\nkey := \"ctx-\" + hex.EncodeToString(sum[:])\nmodel.PatchViewState(key, values, nil)","handlingStrategy":"validation","validationCode":"func isValidViewStateKey(key string) bool {\n    trimmed := strings.TrimSpace(key)\n    return trimmed != \"\" && len(key) <= 1024\n}","typeGuard":"func validViewStateKey(key string) (string, bool) {\n    if key == \"\" || strings.TrimSpace(key) == \"\" || len(key) > 1024 {\n        return \"\", false\n    }\n    return key, true\n}","tryCatchPattern":"if _, err := model.GetViewState(key); err != nil {\n    if strings.Contains(err.Error(), \"invalid view state key\") {\n        key = deriveViewStateKey(fallbackComponents) // short hashed key\n        _, err = model.GetViewState(key)\n    }\n    return err\n}\nreturn nil","preventionTips":["Reject empty/whitespace keys at the UI or API boundary before they reach view state","Keep composite keys short — hash long components instead of concatenating raw IDs, paths, or URLs","Test key construction with worst-case component lengths to confirm the result stays under 1024 bytes"],"tags":["validation","view-state","keys","siyuan"],"backgroundTag":"invalid-identifier-format","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"}