{"record":{"id":"f9a4a0b8aa68a497","repo":"datawhalechina/hello-agents","slug":"error-f9a4a0","errorCode":null,"errorMessage":"启动失败","messagePattern":"启动失败","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"Co-creation-projects/afei-GuessWhoAmI/frontend/app.js","lineNumber":55,"sourceCode":"  }\n\n  // Start new game\n  async startNewGame() {\n    try {\n      this.setStartBtnLoading(true);\n      this.showLoadingOverlay();\n\n      const response = await fetch('http://localhost:8000/api/game/start', {\n        method: 'POST',\n        headers: {'Content-Type': 'application/json'},\n        body: JSON.stringify({})\n      });\n\n      if (!response.ok) throw new Error(`HTTP error: ${response.status}`);\n\n      const result = await response.json();\n\n      if (!result.success) throw new Error(result.error || '启动失败');\n\n      const data = result.data;\n      this.sessionId = data.session_id;\n      this.remainingQuestions = data.max_questions || 20;\n      this.remainingHints = data.max_hints || 3;\n\n      // Switch to game screen\n      document.getElementById('intro-section').classList.add('hidden');\n      document.getElementById('game-section').classList.remove('hidden');\n      document.getElementById('result-modal').classList.add('hidden');\n\n      // Enable controls\n      document.getElementById('user-input').disabled = false;\n      document.getElementById('send-btn').disabled = false;\n      document.getElementById('get-hint').disabled = false;\n      document.getElementById('guess-btn').disabled = false;\n      document.getElementById('guess-input').disabled = false;\n","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/datawhalechina/hello-agents/blob/606a07d341a47be773fab7f4b71177f53f96b2c3/Co-creation-projects/afei-GuessWhoAmI/frontend/app.js#L37-L73","documentation":"Application-level error guard in startNewGame(): the backend returned 2xx and the body parsed as JSON, but result.success is falsy, so it throws result.error or the literal '启动失败'. The backend uses a {success, error, data} envelope; this branch means the game session could not be created for a business reason (no figures loaded, agent init failure).","triggerScenarios":"POST /api/game/start succeeding HTTP-wise but with success:false — e.g. figure pool empty because the data file failed to load, LLM client initialization failed, or max session limits reached. The literal '启动失败' appears only when the backend also omitted error.","commonSituations":"Backend starts but its figure dataset/config is missing; API key for the LLM not configured so session creation aborts; envelope field renamed (ok/status instead of success) after a backend refactor so success is always undefined.","solutions":["Log the full result object to see what the backend actually returned; fix the backend condition that sets success:false","Check backend startup logs for dataset/API-key initialization failures","Verify the envelope contract ({success, error, data}) still matches on both sides after backend changes","Return a specific error string from the backend instead of relying on the frontend fallback"],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":null,"typeGuard":"function isGameStartResult(r) { return r && typeof r.success === 'boolean' && r.data && 'session_id' in r.data; }","tryCatchPattern":"try { const r = await startGame(); if (!r.success) throw new Error(r.error || '启动失败'); } catch (e) { alert(e.message); }","preventionTips":["Backend must always populate error when success is false","Log the raw envelope on failure during development","Pin the envelope shape with a shared type or schema"],"tags":["api-envelope","game","fetch","initialization"],"backgroundTag":null,"analyzedSha":"606a07d341a47be773fab7f4b71177f53f96b2c3","analyzedAt":"2026-08-14T22:57:27.446Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}