{"record":{"id":"4cf2f951a672eeff","repo":"odysseus-dev/odysseus","slug":"http-res-status-4cf2f9","errorCode":null,"errorMessage":"HTTP ${res.status}","messagePattern":"HTTP \\$\\{res\\.status\\}","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"static/js/emailLibrary.js","lineNumber":415,"sourceCode":"        wp = spinnerModule.createWhirlpool(14);\n        wp.element.style.cssText = 'display:inline-block;vertical-align:-3px;margin-right:6px;';\n        status.appendChild(wp.element);\n        status.appendChild(document.createTextNode('Analyzing sent emails…'));\n      } catch (_) {\n        status.textContent = 'Analyzing sent emails…';\n      }\n    }\n    try {\n      const res = await fetch(emailApiUrl('/api/email/extract-style', {\n        account_id: state._libAccountId || undefined,\n      }), {\n        method: 'POST',\n        headers: { 'Content-Type': 'application/json' },\n        credentials: 'include',\n        body: JSON.stringify({ sample_count: 15 }),\n      });\n      const data = await res.json().catch(() => ({}));\n      if (!res.ok || !data.success || !data.style) throw new Error(data.error || `HTTP ${res.status}`);\n      if (styleEl) styleEl.value = data.style;\n      if (status) status.textContent = 'Extracted';\n      showToast?.('Email writing style extracted');\n      setTimeout(() => { if (status) status.textContent = ''; }, 1800);\n    } catch (err) {\n      if (status) status.textContent = err?.message || 'Extract failed';\n      showToast?.('Failed to extract email writing style');\n    } finally {\n      if (wp && wp.destroy) { try { wp.destroy(); } catch (_) {} }\n      extractBtn.disabled = false;\n      if (saveBtn) saveBtn.disabled = false;\n    }\n  });\n}\n\nfunction _hideEmailSettingsPage() {\n  const modal = document.getElementById('email-lib-modal');\n  const page = document.getElementById('email-lib-settings-page');","sourceCodeStart":397,"sourceCodeEnd":433,"githubUrl":"https://github.com/odysseus-dev/odysseus/blob/f9235ebbf13f693a6fd29ce70b097f6ec83705bf/static/js/emailLibrary.js#L397-L433","documentation":"Thrown when POST /api/email/extract-style fails: the guard `!res.ok || !data.success || !data.style` covers HTTP failure, a success=false body, and a missing style payload, with the message coming from data.error or 'HTTP <status>'. The status element then shows the failure reason.","triggerScenarios":"Clicking Extract in the email style settings: server cannot fetch enough sample messages (empty sent folder → no style), the account_id in state is stale, IMAP authentication fails mid-extraction, or the LLM call used to summarize style errors out.","commonSituations":"New account with too few sent messages; OAuth token expired between list and extract; provider rate limit on the style-summarization model; JSON parse failure handled as {} so data.error is undefined and the bare status shows.","solutions":["Read the status text next to the button — it carries data.error when present","Ensure the selected account has sent-folder messages to sample (sample_count: 15 needs history)","Re-authenticate the email account if IMAP/token errors are indicated","Retry after rate limits clear; verify account_id matches a configured account"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { const data = await res.json().catch(() => ({})); if (!res.ok || !data.success || !data.style) throw new Error(data.error || `HTTP ${res.status}`); ... } catch (err) { status.textContent = err?.message || 'Extract failed'; } finally { btn.disabled = false; }","preventionTips":["Require a minimum sent-message count before enabling Extract","Treat success+style as one combined guard (as here) — partial success still fails safely","Reset button/spinner state in finally so failures never lock the UI"],"tags":["email","fetch","style-extraction","llm","account-config"],"backgroundTag":null,"analyzedSha":"f9235ebbf13f693a6fd29ce70b097f6ec83705bf","analyzedAt":"2026-08-14T21:47:48.359Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}