{"record":{"id":"30ac364e7a4b967f","repo":"siyuan-note/siyuan","slug":"failed-to-action-view-state","errorCode":null,"errorMessage":"Failed to ${action} view state","messagePattern":"Failed to (.+?) view state","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"app/src/util/viewState.ts","lineNumber":44,"sourceCode":"\nconst getPatchByteLength = (values: TViewStateData, removeKeys: string[]) => {\n    const json = JSON.stringify({values, removeKeys});\n    if (typeof json !== \"string\") {\n        throw new Error(\"Invalid view state patch\");\n    }\n    const goCompatibleJSON = json.replace(/[<>&\\u2028\\u2029]/g, character => {\n        return `\\\\u${character.charCodeAt(0).toString(16).padStart(4, \"0\")}`;\n    });\n    return new TextEncoder().encode(goCompatibleJSON).byteLength;\n};\n\nconst isViewStateData = (value: unknown): value is TViewStateData => {\n    return typeof value === \"object\" && value !== null && !Array.isArray(value);\n};\n\nconst checkResponse = (response: IWebSocketData, action: string) => {\n    if (!response || response.code !== 0) {\n        throw new Error(response?.msg || `Failed to ${action} view state`);\n    }\n};\n\nconst defaultTransport: IViewStateTransport = {\n    async get(key) {\n        const {fetchSyncPost} = await import(\"./fetch\");\n        const response = await fetchSyncPost(\"/api/storage/getViewState\", {key});\n        checkResponse(response, \"get\");\n        return isViewStateData(response.data) ? response.data : {};\n    },\n    async patch(key, values, removeKeys) {\n        const {fetchSyncPost} = await import(\"./fetch\");\n        const response = await fetchSyncPost(\"/api/storage/patchViewState\", {key, values, removeKeys});\n        checkResponse(response, \"patch\");\n    },\n};\n\nconst validateIdentityPart = (name: string, value: string) => {","sourceCodeStart":26,"sourceCodeEnd":62,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/app/src/util/viewState.ts#L26-L62","documentation":"checkResponse is the response gate for ViewStateService's default transport. When the kernel response for /api/storage/getViewState or /api/storage/patchViewState is missing or returns code !== 0, it throws either the server's msg or this generic `Failed to <action> view state` message. It converts transport-level failures into a uniform exception for get and patch.","triggerScenarios":"Calling ViewStateService.get or patch (via checkResponse, app/src/util/viewState.ts:44) when fetchSyncPost returns undefined/empty (network down, kernel unreachable) or the kernel rejects the request (storage API error, oversized patch beyond MAX_PATCH_BYTES, malformed key).","commonSituations":"Kernel not running or workspace closed; network failure on mobile/remote connections; storage record write rejected server-side; patch payload exceeding size limits.","solutions":["Confirm the kernel is reachable and the workspace is open","Inspect response.msg in the caught error for the kernel-side cause","Reduce patch size (fewer values / removeKeys) if the request was too large","Retry after connectivity is restored; view state patching is debounced so transient failures can be retried safely"],"exampleFix":"// before\nawait service.patch({fontSize: 14});\n// after\ntry {\n    await service.patch({fontSize: 14});\n} catch (e) {\n    if (e.message.includes(\"Failed to patch view state\")) {\n        queueRetry(() => service.patch({fontSize: 14}));\n    }\n}","handlingStrategy":"retry","validationCode":"// ensure kernel reachable before heavy state usage\nconst ping = await fetchPost(\"/api/system/version\", {});","typeGuard":null,"tryCatchPattern":"try { await checkResponseWork(); } catch (e) { if (e.message.startsWith(\"Failed to\")) retryWithBackoff(); else throw e; }","preventionTips":["Check kernel connectivity before relying on view state persistence","Keep patches under the 256KB / 1000-entry limits","Debounce and retry transient transport failures"],"tags":["api","storage","view-state"],"backgroundTag":"api-request-failed","analyzedSha":"9f775e8a12daef8255556097396f9b2739078892","analyzedAt":"2026-09-19T03:17:15.984Z","contentChangedAt":"2026-09-19T03:17:15.984Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}