siyuan-note/siyuan · error · Error

Failed to view state

Error message

Failed to ${action} view state

What it means

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.

Solutions

  1. Confirm the kernel is reachable and the workspace is open
  2. Inspect response.msg in the caught error for the kernel-side cause
  3. Reduce patch size (fewer values / removeKeys) if the request was too large
  4. Retry after connectivity is restored; view state patching is debounced so transient failures can be retried safely

Example fix

// before
await service.patch({fontSize: 14});
// after
try {
    await service.patch({fontSize: 14});
} catch (e) {
    if (e.message.includes("Failed to patch view state")) {
        queueRetry(() => service.patch({fontSize: 14}));
    }
}
Defensive patterns

Strategy: retry

Validate before calling

// ensure kernel reachable before heavy state usage
const ping = await fetchPost("/api/system/version", {});

Try / catch

try { await checkResponseWork(); } catch (e) { if (e.message.startsWith("Failed to")) retryWithBackoff(); else throw e; }

Prevention

When it happens

Trigger: 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).

Common situations: Kernel not running or workspace closed; network failure on mobile/remote connections; storage record write rejected server-side; patch payload exceeding size limits.

Understand the failure class

Background: "API request failed": what wrapped HTTP errors from external APIs mean and how to find the real cause — this error's family across 29 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19). Data as JSON: /api/errors/30ac364e7a4b967f. Report an issue: GitHub.

Appendix: source

Thrown at app/src/util/viewState.ts:44

const getPatchByteLength = (values: TViewStateData, removeKeys: string[]) => {
    const json = JSON.stringify({values, removeKeys});
    if (typeof json !== "string") {
        throw new Error("Invalid view state patch");
    }
    const goCompatibleJSON = json.replace(/[<>&\u2028\u2029]/g, character => {
        return `\\u${character.charCodeAt(0).toString(16).padStart(4, "0")}`;
    });
    return new TextEncoder().encode(goCompatibleJSON).byteLength;
};

const isViewStateData = (value: unknown): value is TViewStateData => {
    return typeof value === "object" && value !== null && !Array.isArray(value);
};

const checkResponse = (response: IWebSocketData, action: string) => {
    if (!response || response.code !== 0) {
        throw new Error(response?.msg || `Failed to ${action} view state`);
    }
};

const defaultTransport: IViewStateTransport = {
    async get(key) {
        const {fetchSyncPost} = await import("./fetch");
        const response = await fetchSyncPost("/api/storage/getViewState", {key});
        checkResponse(response, "get");
        return isViewStateData(response.data) ? response.data : {};
    },
    async patch(key, values, removeKeys) {
        const {fetchSyncPost} = await import("./fetch");
        const response = await fetchSyncPost("/api/storage/patchViewState", {key, values, removeKeys});
        checkResponse(response, "patch");
    },
};

const validateIdentityPart = (name: string, value: string) => {

View on GitHub (pinned to 9f775e8a12)