{"record":{"id":"f3a09b6fdbc40267","repo":"datawhalechina/hello-agents","slug":"error-f3a09b","errorCode":null,"errorMessage":"大纲生成失败: ","messagePattern":"大纲生成失败: ","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"Co-creation-projects/lgs-only-NovelGenerator/frontend/index.html","lineNumber":383,"sourceCode":"                        // 构建 style_tags\n                        const styleTags = {\n                            'channel': outlineInput.channel,\n                            'style': outlineInput.style\n                        };\n                        \n                        const res = await fetch(`${API_URL}/outline/generate`, {\n                            method: 'POST',\n                            headers: {'Content-Type': 'application/json'},\n                            body: JSON.stringify({\n                                novel_id: project.novel_id,\n                                title: project.title,\n                                user_input: outlineInput.user_input,\n                                target_length: outlineInput.target_length,\n                                style_tags: styleTags\n                            })\n                        });\n                        \n                        if (!res.ok) throw new Error(await res.text());\n                        \n                        const data = await res.json();\n                        outline.id = data.note_id;\n                        outline.content = data.content;\n                    } catch (e) {\n                        alert('大纲生成失败: ' + e);\n                    } finally {\n                        loading.value = false;\n                        currentAction.value = null;\n                    }\n                };\n\n                const updateOutline = async () => {\n                    if (!outline.id) return;\n                    loading.value = true;\n                    currentAction.value = 'update_outline';\n                    try {\n                        const res = await fetch(`${API_URL}/outline/update`, {","sourceCodeStart":365,"sourceCodeEnd":401,"githubUrl":"https://github.com/datawhalechina/hello-agents/blob/606a07d341a47be773fab7f4b71177f53f96b2c3/Co-creation-projects/lgs-only-NovelGenerator/frontend/index.html#L365-L401","documentation":"'大纲生成失败: ' + e (outline generation failed) is alerted by the NovelGenerator frontend when POST {API_URL}/outline/generate responds non-OK; the thrown Error wraps the raw response text (await res.text()). Note the string-concatenation of an Error object yields 'Error: <server text>', so the alert shows the server's body — commonly an HTML error page or FastAPI detail JSON, which is ugly but informative.","triggerScenarios":"POST /outline/generate with {novel_id, title, user_input, target_length, style_tags} returns 404 (API_URL wrong / route missing), 422 (target_length not a number, empty user_input, style_tags not a list), 500 (LLM generation failure, invalid API key), 502 backend down. Note novel_id comes from project state — a stale/unsaved project id also triggers backend 404s.","commonSituations":"API_URL constant pointing at the wrong host/port; project created in a previous backend run (memory store reset) so novel_id is unknown; LLM key missing server-side; target_length sent as string from a form input.","solutions":["Read the alert content after the colon — it is the raw server response body and names the actual error (e.g. FastAPI {'detail': ...}).","Verify API_URL matches the running backend and that /outline/generate exists there.","If the detail mentions a missing novel/project, re-create or re-select the project so novel_id is current.","Check target_length/style_tags types against the backend schema before sending."],"exampleFix":"// before\nif (!res.ok) throw new Error(await res.text());\n// ...\nalert('大纲生成失败: ' + e);\n\n// after\nif (!res.ok) {\n  const t = await res.text();\n  throw new Error(`${res.status}: ${t.slice(0, 200)}`);\n}\n// ...\nalert('大纲生成失败: ' + (e instanceof Error ? e.message : String(e)));","handlingStrategy":"validation","validationCode":"if (!project.novel_id) { alert('请先创建或加载项目'); return; }\nif (!outlineInput.user_input?.trim()) { alert('请填写大纲需求描述'); return; }\nif (!Number.isFinite(Number(outlineInput.target_length))) { alert('目标字数必须是数字'); return; }","typeGuard":"function isOutlineGenerateResponse(d: unknown): d is { note_id: string; content: string } {\n  return typeof d === 'object' && d !== null\n    && typeof (d as { note_id?: unknown }).note_id === 'string'\n    && typeof (d as { content?: unknown }).content === 'string';\n}","tryCatchPattern":"try {\n  const res = await fetch(`${API_URL}/outline/generate`, opts);\n  if (!res.ok) {\n    const detail = await res.text();\n    throw new Error(`${res.status}: ${detail.slice(0, 200)}`);\n  }\n  const data = await res.json();\n  if (!isOutlineGenerateResponse(data)) throw new Error('大纲响应格式异常');\n} catch (e) {\n  alert('大纲生成失败: ' + (e instanceof Error ? e.message : String(e)));\n}","preventionTips":["Validate project.novel_id and numeric fields before sending — most 4xx here are preventable.","Show e.message, not the concatenated Error object, in alerts.","Confirm API_URL is set for the environment (dev vs prod) before release."],"tags":["http","fetch","novel-generation","api-client"],"backgroundTag":null,"analyzedSha":"606a07d341a47be773fab7f4b71177f53f96b2c3","analyzedAt":"2026-08-14T22:57:27.446Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}