{"record":{"id":"506544f3ccea42d6","repo":"BigPizzaV3/CodexPlusPlus","slug":"error","errorCode":null,"errorMessage":"收到未加密数据包","messagePattern":"收到未加密数据包","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/codex-plus-mobile-relay/src/main.rs","lineNumber":810,"sourceCode":"  if (!crypto?.subtle) throw new Error(\"当前页面不是安全上下文，WebCrypto 不可用\");\n  const raw = new TextEncoder().encode($(\"key\").value);\n  const digest = await crypto.subtle.digest(\"SHA-256\", raw);\n  return crypto.subtle.importKey(\"raw\", digest, \"AES-GCM\", false, [\"encrypt\", \"decrypt\"]);\n}\nasync function encrypt(payload) {\n  if (!crypto?.subtle) {\n    setStatus(\"当前浏览器禁用 WebCrypto，已使用兼容模式\", true);\n    return { type: \"plaintext\", payload };\n  }\n  const key = await cryptoKey();\n  const nonce = crypto.getRandomValues(new Uint8Array(12));\n  const plain = new TextEncoder().encode(JSON.stringify(payload));\n  const encrypted = await crypto.subtle.encrypt({ name: \"AES-GCM\", iv: nonce }, key, plain);\n  return { type: \"encrypted\", nonce: b64url(nonce), payload: b64url(encrypted) };\n}\nasync function decrypt(envelope) {\n  if (envelope?.type === \"plaintext\") return envelope.payload;\n  if (!envelope || envelope.type !== \"encrypted\") throw new Error(\"收到未加密数据包\");\n  const key = await cryptoKey();\n  const nonce = b64urlDecode(envelope.nonce);\n  const data = b64urlDecode(envelope.payload);\n  const plain = await crypto.subtle.decrypt({ name: \"AES-GCM\", iv: nonce }, key, data);\n  return JSON.parse(new TextDecoder().decode(plain));\n}\nasync function connect() {\n  const room = encodeURIComponent($(\"room\").value.trim());\n  if (!room || !$(\"key\").value) { setStatus(\"需要房间 ID 和 Key\", true); return; }\n  const scheme = location.protocol === \"https:\" ? \"wss\" : \"ws\";\n  if (socket) try { socket.close(); } catch {}\n  socket = new WebSocket(`${scheme}://${location.host}/client?room=${room}&token=${room}`);\n  socket.onopen = async () => { setStatus(\"已连接 relay，正在读取会话...\"); try { await loadSessions(); } catch (e) { setStatus(e.message, true); } };\n  socket.onclose = () => { appServerConnected = false; setStatus(\"已断开\"); };\n  socket.onerror = () => setStatus(\"连接错误\", true);\n  socket.onmessage = async (event) => {\n    try {\n      const message = JSON.parse(event.data);","sourceCodeStart":792,"sourceCodeEnd":828,"githubUrl":"https://github.com/BigPizzaV3/CodexPlusPlus/blob/f2074595a281bc057525c748175c8eb9805b0673/apps/codex-plus-mobile-relay/src/main.rs#L792-L828","documentation":"Raised in mobile_relay_page when a WebSocket packet arrives without the expected AES-GCM encrypted envelope: plaintext or malformed data was received, typically from a key/protocol mismatch between browser and relay or a non-relay client sending frames.","triggerScenarios":"Thrown at apps/codex-plus-mobile-relay/src/main.rs:810 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Confirm both ends use the same access key so encryption modes match","Reload the page to renegotiate with the current relay protocol","Check no proxy is rewriting WebSocket frames"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"f2074595a281bc057525c748175c8eb9805b0673","analyzedAt":"2026-08-23T12:52:24.489Z","contentChangedAt":"2026-08-23T12:52:24.489Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}