{"record":{"id":"8bad238466b881e0","repo":"datawhalechina/hello-agents","slug":"error-8bad23","errorCode":null,"errorMessage":"推荐失败","messagePattern":"推荐失败","errorType":"exception","errorClass":"ApiError","httpStatus":null,"severity":"error","filePath":"Co-creation-projects/aatanxiao12-beep-YingQian/frontend/src/pages/HomePage.tsx","lineNumber":90,"sourceCode":"\n    const seen = loadSeen()\n    const merged: RecommendRequest = {\n      ...request,\n      exclude_titles: [\n        ...new Set([\n          ...request.exclude_titles,\n          ...seen.map((s) => s.title),\n        ]),\n      ],\n      exclude_ids: [\n        ...new Set([...request.exclude_ids, ...seen.map((s) => s.id)]),\n      ],\n    }\n\n    try {\n      const res = await postRecommend(merged)\n      if (!res.success || !res.data) {\n        throw new ApiError(res.message || '推荐失败')\n      }\n\n      setStageIndex(PROGRESS_STAGES.length - 1)\n      saveSession({\n        request: merged,\n        result: res.data,\n        message: res.message,\n      })\n      navigate('/result')\n    } catch (err) {\n      setError(err instanceof Error ? err.message : '推荐失败，请稍后重试')\n    } finally {\n      stopFakeProgress()\n      setLoading(false)\n    }\n  }\n\n  return (","sourceCodeStart":72,"sourceCodeEnd":108,"githubUrl":"https://github.com/datawhalechina/hello-agents/blob/606a07d341a47be773fab7f4b71177f53f96b2c3/Co-creation-projects/aatanxiao12-beep-YingQian/frontend/src/pages/HomePage.tsx#L72-L108","documentation":"'推荐失败' (recommendation failed) is thrown in beep-YingQian's HomePage when the wrapped recommendation API postRecommend() resolves with success=false or no data — i.e. the HTTP call succeeded but the application-level envelope marks it a failure, or the envelope lacked any message. The catch also reuses the string as the generic user-facing fallback when a non-Error value is thrown.","triggerScenarios":"POST to the recommend endpoint returns 200 with {success:false, message?} — backend couldn't build a recommendation (e.g. insufficient watched-movie history, all candidates excluded by exclude_titles/exclude_ids, upstream recommender/LLM error) — or returns success:true with data missing. The merged request dedupes exclude_ids with previously seen titles, so an over-excluded user can exhaust the candidate pool.","commonSituations":"New user with no history so the recommender has nothing to rank; user clicked '换一批' (change batch) repeatedly in a prior session so seen-list exclusions eliminated all candidates; backend message field empty so the generic text is shown.","solutions":["Inspect the actual response in DevTools — when success=false the backend message (if any) names the real cause and this error only fires when it's absent.","If exclusions exhausted the pool, reset the session (clear saved seen/exclude state in sessionId storage) or relax exclude merging for cold-start users.","Check backend logs for the recommender service; success=false often wraps an upstream model failure.","Make the backend always return a non-empty message so users see the specific cause instead of this generic string."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"const seenCount = seen.length;\nif (seenCount > MAX_EXCLUSIONS) {\n  // pool likely exhausted; drop oldest exclusions\n  seen.splice(0, seenCount - MAX_EXCLUSIONS);\n}\nif (!request || !Array.isArray(request.exclude_ids)) {\n  throw new Error('推荐请求缺少排除列表');\n}","typeGuard":"function isRecommendSuccess(res: unknown): res is { success: true; data: NonNullable<unknown>; message?: string } {\n  return typeof res === 'object' && res !== null\n    && (res as { success?: unknown }).success === true\n    && 'data' in (res as object);\n}","tryCatchPattern":"try {\n  const res = await postRecommend(merged);\n  if (!isRecommendSuccess(res)) {\n    showNotice(res?.message || '暂无更多推荐，请调整偏好后重试');\n    return;\n  }\n  // success path\n} catch (err) {\n  setError(err instanceof Error ? err.message : '推荐失败，请稍后重试');\n}","preventionTips":["Cap exclude_ids/seen lists so the candidate pool can't be exhausted by heavy use.","Treat success=false with empty data as an empty state, not an exception, when the backend message says so.","Confirm the backend always populates message on failure so generic text never appears."],"tags":["api-envelope","recommendation","business-logic","cold-start"],"backgroundTag":null,"analyzedSha":"606a07d341a47be773fab7f4b71177f53f96b2c3","analyzedAt":"2026-08-14T22:57:27.446Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}