{"record":{"id":"b3652ccf3f067a21","repo":"wavetermdev/waveterm","slug":"encryption-is-not-available","errorCode":null,"errorMessage":"encryption is not available","messagePattern":"encryption is not available","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"emain/emain-wsh.ts","lineNumber":68,"sourceCode":"        if (ww == null) {\n            const window = await WindowService.GetWindow(windowId);\n            if (window == null) {\n                throw new Error(`window ${windowId} not found`);\n            }\n            ww = await createBrowserWindow(window, fullConfig, {\n                unamePlatform,\n                isPrimaryStartupWindow: false,\n            });\n        }\n        ww.focus();\n    }\n\n    async handle_electronencrypt(\n        rh: RpcResponseHelper,\n        data: CommandElectronEncryptData\n    ): Promise<CommandElectronEncryptRtnData> {\n        if (!safeStorage.isEncryptionAvailable()) {\n            throw new Error(\"encryption is not available\");\n        }\n        const encrypted = safeStorage.encryptString(data.plaintext);\n        const ciphertext = encrypted.toString(\"base64\");\n\n        let storagebackend = \"\";\n        if (process.platform === \"linux\") {\n            storagebackend = safeStorage.getSelectedStorageBackend();\n        }\n\n        return {\n            ciphertext,\n            storagebackend,\n        };\n    }\n\n    async handle_electrondecrypt(\n        rh: RpcResponseHelper,\n        data: CommandElectronDecryptData","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/emain/emain-wsh.ts#L50-L86","documentation":"StartConnServer launches the remote wsh connserver and, like OpenDomainSocketListener, is only permitted while the WslConn status is Status_Connecting. If the lock-protected status check fails, it returns this error with the connection name and actual status. It prevents starting a second conn server for an already-established or already-failed connection.","triggerScenarios":"tryEnableWsh calls StartConnServer when Status is not Status_Connecting — e.g. already connected, already starting, or disconnected.","commonSituations":"Concurrent/attempted duplicate StartConnServer calls; conn already fully connected so no server start is needed; connection transitioned to error state between calls; racing reconnect flows.","solutions":["Verify conn.GetStatus() is Status_Connecting before calling","If the conn is already connected, skip StartConnServer — the server is already running","De-duplicate enable flows (guard with a flag or mutex) so it is only invoked once","If status is disconnected/error, reconnect the base connection first"],"exampleFix":"// before\nconn.StartConnServer(ctx, false) // fails unless status == Connecting\n// after\nif conn.GetStatus() != wslconn.Status_Connecting {\n    return nil // already connected or not ready; skip server start\n}\nstarted, _, _, err := conn.StartConnServer(ctx, false)","handlingStrategy":"type-guard","validationCode":"if conn.GetStatus() != wslconn.Status_Connecting {\n    return nil // server already started or conn not ready\n}","typeGuard":"func canStartServer(s string) bool { return s == wslconn.Status_Connecting }","tryCatchPattern":"started, _, _, err := conn.StartConnServer(ctx, false)\nif err != nil && strings.Contains(err.Error(), \"cannot start conn server\") {\n    // inspect conn.GetStatus(); skip if already connected\n}","preventionTips":["Guard StartConnServer behind a single-flight/once mechanism","Check status immediately before the call; status can change asynchronously","Treat duplicate enable attempts as no-ops, not errors"],"tags":["wsl","connection-state","connserver","race-condition"],"backgroundTag":"invalid-connection-state","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}