{"record":{"id":"bcacbd78b9fa8b77","repo":"datawhalechina/hello-agents","slug":"error-bcacbd","errorCode":null,"errorMessage":"更新失败: ","messagePattern":"更新失败: ","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"Co-creation-projects/lgs-only-NovelGenerator/frontend/index.html","lineNumber":542,"sourceCode":"                    }\n                };\n\n                const updateChapter = async (chapter) => {\n                    loading.value = true;\n                    currentAction.value = 'update_chapter_' + chapter.id;\n                    try {\n                        const res = await fetch(`${API_URL}/chapter/update`, {\n                            method: 'PUT',\n                            headers: {'Content-Type': 'application/json'},\n                            body: JSON.stringify({\n                                novel_id: project.novel_id,\n                                title: project.title,\n                                note_id: chapter.id,\n                                content: chapter.content,\n                                chapter_title: chapter.title // 支持修改标题\n                            })\n                        });\n                        if (!res.ok) throw new Error(await res.text());\n                        alert('章节更新成功');\n                    } catch (e) {\n                        alert('更新失败: ' + e);\n                    } finally {\n                        loading.value = false;\n                        currentAction.value = null;\n                    }\n                };\n\n                const deleteChapter = async (chapter) => {\n                    if(!confirm('确定要删除这一章吗？')) return;\n                    loading.value = true;\n                    currentAction.value = 'delete_chapter_' + chapter.id;\n                    try {\n                        const params = new URLSearchParams({\n                            novel_id: project.novel_id,\n                            title: project.title,\n                            note_id: chapter.id","sourceCodeStart":524,"sourceCodeEnd":560,"githubUrl":"https://github.com/datawhalechina/hello-agents/blob/606a07d341a47be773fab7f4b71177f53f96b2c3/Co-creation-projects/lgs-only-NovelGenerator/frontend/index.html#L524-L560","documentation":"'更新失败: ' + e (update failed) is alerted by the NovelGenerator frontend when PUT {API_URL}/chapter/update responds non-OK; the thrown Error wraps the response body text. The request updates an existing chapter {novel_id, title, note_id, content, chapter_title}; note_id is chapter.id from the local list, so stale ids after backend state loss are the dominant cause.","triggerScenarios":"PUT /chapter/update returns 404 (chapter.id unknown — backend restarted, chapter deleted, or id from a failed generate), 422 (chapter_title/content missing or empty because the edit wasn't saved), 500 storage failure. Editing a chapter whose generation never completed (id never assigned) also produces doomed requests.","commonSituations":"Editing right after a backend restart wiped in-memory chapters; chapter_title left blank; saving an edit on a chapter that failed to generate (no valid id).","solutions":["Guard: only enable chapter editing when chapter.id is truthy.","Read the alert body — it distinguishes not-found from validation errors.","Require chapter_title and content non-empty before the PUT.","On 404, refresh the chapter list from the server to resync ids."],"exampleFix":"// before\nconst updateChapter = async (chapter) => { /* no guard */ }\n\n// after\nconst updateChapter = async (chapter) => {\n  if (!chapter.id) { alert('该章节尚未生成，无法更新'); return; }\n  if (!chapter.title?.trim() || !chapter.content?.trim()) { alert('标题和内容不能为空'); return; }\n  // ... existing fetch\n}","handlingStrategy":"validation","validationCode":"if (!chapter.id) { alert('该章节尚未生成，无法更新'); return; }\nif (!chapter.title?.trim() || !chapter.content?.trim()) { alert('章节标题和内容不能为空'); return; }","typeGuard":"function isChapterUpdatePayload(p: unknown): p is { novel_id: string; title: string; note_id: string; content: string; chapter_title: string } {\n  return typeof p === 'object' && p !== null\n    && typeof (p as { note_id?: unknown }).note_id === 'string'\n    && typeof (p as { chapter_title?: unknown }).chapter_title === 'string';\n}","tryCatchPattern":"try {\n  const res = await fetch(`${API_URL}/chapter/update`, opts);\n  if (!res.ok) throw new Error(`${res.status}: ${(await res.text()).slice(0, 200)}`);\n  alert('章节更新成功');\n} catch (e) {\n  const m = e instanceof Error ? e.message : String(e);\n  if (m.startsWith('404')) refreshChapterList(); // resync stale ids\n  else alert('更新失败: ' + m);\n}","preventionTips":["Gate edit/save UI on chapter.id being present.","On 404, refetch the chapter list to resynchronize ids after backend state loss.","Require non-empty title and content client-side before the PUT."],"tags":["http","fetch","crud","stale-id","novel-generation"],"backgroundTag":null,"analyzedSha":"606a07d341a47be773fab7f4b71177f53f96b2c3","analyzedAt":"2026-08-14T22:57:27.446Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}