{"record":{"id":"3098d8b178db93aa","repo":"jd-opensource/joyagent-jdgenie","slug":"error-3098d8","errorCode":null,"errorMessage":"网络错误","messagePattern":"网络错误","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"ui/src/components/ActionPanel/TableRenderer.tsx","lineNumber":35,"sourceCode":"  /**\n   * 文件类型，默认为文件扩展名决定\n   */\n  mode?: 'csv' | 'excel';\n  /**\n   * 文件名\n   */\n  fileName?: string;\n}> = (props) => {\n  const { fileUrl, mode, fileName } = props;\n\n  const ext = (fileName || fileUrl).split('.').pop()?.toLowerCase();\n\n  const fileType = mode || (ext === 'xlsx' || ext === 'xlsm' || ext === 'xlsb' || ext === 'xls' ? 'excel' : 'csv');\n\n  // 拉取 CSV 文本\n  const { data, loading, error } = useRequest(async () => {\n    const res = await fetch(fileUrl);\n    if (!res.ok) throw new Error('网络错误');\n\n    if (fileType === 'excel') {\n      return res.arrayBuffer();\n    }\n\n    return res.text();\n  },\n  { refreshDeps: [fileUrl] }\n  );\n\n  // 解析 CSV\n  const { columns, dataSource, parseError } = useMemo(() => {\n    if (!data) return {\n      columns: [],\n      dataSource: [],\n      parseError: false\n    };\n","sourceCodeStart":17,"sourceCodeEnd":53,"githubUrl":"https://github.com/jd-opensource/joyagent-jdgenie/blob/2417e0b8b636d941ad5fb14c59b20dddfef5375d/ui/src/components/ActionPanel/TableRenderer.tsx#L17-L53","documentation":"TableRenderer fetches fileUrl and throws Error('网络错误') ('network error') when res.ok is false, i.e. any non-2xx HTTP status, before parsing the CSV/Excel content. The table cannot render without the file data.","triggerScenarios":"The spreadsheet URL returns 404 (file missing), 403 (expired link or denied access), or 5xx server error; a wrong fileUrl passed via props.","commonSituations":"Excel/CSV exported files deleted by cleanup jobs; presigned URL expiry; permission changes on the storage bucket; misconfigured base path in fileUrl.","solutions":["Confirm fileUrl resolves (open it in a browser) and returns 200","Regenerate or refresh the file download URL","Render the `error` state from useRequest with a retry action","Check that the file type/mode matches the actual file (excel vs csv handling)","Inspect the storage service for why the object is unavailable"],"exampleFix":"// before\nconst res = await fetch(fileUrl);\nif (!res.ok) throw new Error('网络错误');\n// after\nconst res = await fetch(fileUrl);\nif (!res.ok) {\n  throw new Error(`表格加载失败 (HTTP ${res.status})`);\n}\nreturn fileType === 'excel' ? res.arrayBuffer() : res.text();","handlingStrategy":"try-catch","validationCode":"async function assertTableAvailable(url: string): Promise<boolean> {\n  try {\n    const res = await fetch(url, { method: 'HEAD' });\n    return res.ok;\n  } catch { return false; }\n}","typeGuard":"function isOk(res: Response): res is Response & { ok: true } {\n  return res.ok;\n}","tryCatchPattern":"const { data, error, run } = useRequest(() => loadTable(fileUrl, fileType), {\n  refreshDeps: [fileUrl],\n  onError: (e) => message.error(`表格加载失败：${e.message}`),\n});\nif (error) return <Button onClick={run}>重新加载</Button>;","preventionTips":["Check res.status and include it in the thrown message for easier debugging","Handle 401/403 by refreshing credentials before fetching","Refresh file URLs when the file list reloads","Distinguish excel vs csv by actual content type, not just extension"],"tags":["react","fetch","network","csv","excel"],"backgroundTag":"http-error-response","analyzedSha":"2417e0b8b636d941ad5fb14c59b20dddfef5375d","analyzedAt":"2026-09-08T11:28:19.414Z","contentChangedAt":"2026-09-08T11:28:19.414Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}