datawhalechina/hello-agents · error · ApiError

推荐失败

Error message

推荐失败

What it means

'推荐失败' (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.

Source

Thrown at Co-creation-projects/aatanxiao12-beep-YingQian/frontend/src/pages/HomePage.tsx:90

    const seen = loadSeen()
    const merged: RecommendRequest = {
      ...request,
      exclude_titles: [
        ...new Set([
          ...request.exclude_titles,
          ...seen.map((s) => s.title),
        ]),
      ],
      exclude_ids: [
        ...new Set([...request.exclude_ids, ...seen.map((s) => s.id)]),
      ],
    }

    try {
      const res = await postRecommend(merged)
      if (!res.success || !res.data) {
        throw new ApiError(res.message || '推荐失败')
      }

      setStageIndex(PROGRESS_STAGES.length - 1)
      saveSession({
        request: merged,
        result: res.data,
        message: res.message,
      })
      navigate('/result')
    } catch (err) {
      setError(err instanceof Error ? err.message : '推荐失败,请稍后重试')
    } finally {
      stopFakeProgress()
      setLoading(false)
    }
  }

  return (

View on GitHub (pinned to 606a07d341)

Solutions

  1. 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.
  2. If exclusions exhausted the pool, reset the session (clear saved seen/exclude state in sessionId storage) or relax exclude merging for cold-start users.
  3. Check backend logs for the recommender service; success=false often wraps an upstream model failure.
  4. Make the backend always return a non-empty message so users see the specific cause instead of this generic string.
Defensive patterns

Strategy: validation

Validate before calling

const seenCount = seen.length;
if (seenCount > MAX_EXCLUSIONS) {
  // pool likely exhausted; drop oldest exclusions
  seen.splice(0, seenCount - MAX_EXCLUSIONS);
}
if (!request || !Array.isArray(request.exclude_ids)) {
  throw new Error('推荐请求缺少排除列表');
}

Type guard

function isRecommendSuccess(res: unknown): res is { success: true; data: NonNullable<unknown>; message?: string } {
  return typeof res === 'object' && res !== null
    && (res as { success?: unknown }).success === true
    && 'data' in (res as object);
}

Try / catch

try {
  const res = await postRecommend(merged);
  if (!isRecommendSuccess(res)) {
    showNotice(res?.message || '暂无更多推荐,请调整偏好后重试');
    return;
  }
  // success path
} catch (err) {
  setError(err instanceof Error ? err.message : '推荐失败,请稍后重试');
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of datawhalechina/hello-agents@606a07d341 (2026-08-14). Data as JSON: /api/errors/8bad238466b881e0. Report an issue: GitHub.