{"record":{"id":"e950f6202304c2a1","repo":"yikart/AiToEarn","slug":"http-error-status-response-status","errorCode":null,"errorMessage":"HTTP error! status: ${response.status}","messagePattern":"HTTP error! status: (.+?)","errorType":"http","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"project/aitoearn-web/src/api/ai/ai.api.ts","lineNumber":437,"sourceCode":"    headers: {\n      'Content-Type': 'application/json',\n      'Authorization': token ? `Bearer ${token}` : '',\n      'Accept-Language': lang || 'en',\n    },\n    body: JSON.stringify({\n      stream: false, // 使用非流式响应\n      model: 'gpt-5.1-all',\n      temperature: 1,\n      presence_penalty: 0,\n      frequency_penalty: 0,\n      top_p: 1,\n      max_tokens: 8000, // 增加到8000以支持更长的响应（包括base64图片）\n      ...data,\n    }),\n  })\n\n  if (!response.ok) {\n    throw new Error(`HTTP error! status: ${response.status}`)\n  }\n\n  return response\n}\n\n/**\n * 获取 Agent 生成的素材列表\n * @param params - 分页参数\n * @param params.page - 页码\n * @param params.pageSize - 每页数量\n * @returns 素材列表\n */\nexport function getAgentAssets(params?: AiPaginationParams) {\n  return http.get<AssetListVo>('ai/assets', params)\n}\n\n/** 创建 AI 批量生成草稿任务 */\nexport function apiCreateDraftGeneration(data: CreateVideoDraftGenerationParams) {","sourceCodeStart":419,"sourceCodeEnd":455,"githubUrl":"https://github.com/yikart/AiToEarn/blob/d3aa8bea5b146a8675607cf0144d891aad3e9683/project/aitoearn-web/src/api/ai/ai.api.ts#L419-L455","documentation":" thrown by aiChatStream's fetch wrapper when the HTTP response is not ok. It is a minimal non-ok guard that surfaces only the numeric status, discarding the response body which likely contains the real error JSON.","triggerScenarios":"POSTing the chat completion request when the AI backend returns a non-2xx status: 401 bad/expired key, 400 invalid params, 429 rate limit, 5xx backend failure — any case where response.ok is false.","commonSituations":"max_tokens or payload exceeding provider limits; model name no longer supported; API key rotated on the server; rate limiting during bursts.","solutions":["Log response.status and read response.text() before throwing to capture the server's error detail.","Handle 429 with backoff retry, 401 with token refresh, 4xx with payload validation.","Verify the request body (model, max_tokens, messages) against the current provider/backend contract.","Check backend health if 5xx statuses recur."],"exampleFix":"// before\nif (!response.ok) {\n  throw new Error(`HTTP error! status: ${response.status}`)\n}\n// after\nif (!response.ok) {\n  const detail = await response.text().catch(() => '')\n  throw new Error(`HTTP error! status: ${response.status} body: ${detail}`)\n}","handlingStrategy":"try-catch","validationCode":"// validate request before fetch\nif (!data.model) throw new Error('model is required')\nif (!Array.isArray(data.messages) || data.messages.length === 0) throw new Error('messages required')","typeGuard":"function isHttpError(e: unknown): e is Error & { status?: number } {\n  if (!(e instanceof Error)) return false\n  const m = /status: (\\d{3})/.exec(e.message)\n  ;(e as any).status = m ? Number(m[1]) : undefined\n  return true\n}","tryCatchPattern":"try {\n  const resp = await aiChatStream(payload)\n}\ncatch (e) {\n  const status = /status: (\\d{3})/.exec(e instanceof Error ? e.message : '')?.[1]\n  if (status === '429') await backoffAndRetry()\n  else if (status === '401') await refreshTokenAndRetry()\n  else showError(e)\n}","preventionTips":["Always check response.ok and read the error body for diagnostics before throwing.","Handle 429 with retry-after backoff, not immediate failure.","Keep max_tokens and model names within the provider's current limits.","Centralize fetch error handling so status-specific logic lives in one place."],"tags":["http","fetch","ai","streaming"],"backgroundTag":"http-non-ok-response","analyzedSha":"d3aa8bea5b146a8675607cf0144d891aad3e9683","analyzedAt":"2026-08-31T14:19:24.185Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}