{"record":{"id":"82d98642f6c9174d","repo":"bytedance/deer-flow","slug":"failed-to-fetch-subtask-steps-res-status","errorCode":null,"errorMessage":"Failed to fetch subtask steps: ${res.status}","messagePattern":"Failed to fetch subtask steps: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"frontend/src/core/tasks/api.ts","lineNumber":49,"sourceCode":"    threadId,\n  )}/runs/${encodeURIComponent(runId)}/events`;\n\n  const events: FetchedEvent[] = [];\n  let afterSeq: number | undefined;\n\n  for (let page = 0; page < SUBTASK_STEPS_MAX_PAGES; page++) {\n    const params = new URLSearchParams({\n      event_types: \"subagent.step\",\n      task_id: taskId,\n      limit: String(pageSize),\n    });\n    if (afterSeq !== undefined) {\n      params.set(\"after_seq\", String(afterSeq));\n    }\n\n    const res = await fetch(`${base}?${params.toString()}`);\n    if (!res.ok) {\n      throw new Error(`Failed to fetch subtask steps: ${res.status}`);\n    }\n    const batch = (await res.json()) as FetchedEvent[];\n    events.push(...batch);\n\n    if (batch.length < pageSize) {\n      break;\n    }\n    const lastSeq = batch[batch.length - 1]?.seq;\n    if (lastSeq === undefined) {\n      break; // can't advance the cursor; stop rather than refetch page 0 forever\n    }\n    afterSeq = lastSeq;\n  }\n\n  return eventsToSteps(events, taskId);\n}\n","sourceCodeStart":31,"sourceCodeEnd":66,"githubUrl":"https://github.com/bytedance/deer-flow/blob/1dd6ba1acb03700589994b0366c5d1c7d05e2eff/frontend/src/core/tasks/api.ts#L31-L66","documentation":"Thrown when a paginated GET of thread events filtered to event_types=subagent.step&task_id=... fails. The loop pages through the event stream (limit=pageSize, after_seq cursor) up to SUBTASK_STEPS_MAX_PAGES to reconstruct subtask steps client-side. Any non-2xx page aborts the whole fetch with only the numeric status in the message.","triggerScenarios":"Fetching steps for a deleted or expired thread (404); unauthenticated access to another user's thread events (403); events endpoint returning 500 during heavy event writes; after_seq pointing past retention boundaries.","commonSituations":"Subtask panel loading an old thread whose events were pruned by retention; session expiry mid-pagination; backend version where the event-types filter param changed.","solutions":["On 404/403, stop showing the subtask panel for that task instead of erroring the whole view","Confirm the thread exists via GET /api/threads/{id} before opening subtasks","Check the raw URL in devtools to verify event_types/task_id/after_seq query encoding","If 500s correlate with load, retry the single failed page with the same cursor after a short delay"],"exampleFix":"// before\nconst res = await fetch(`${base}?${params.toString()}`);\nif (!res.ok) throw new Error(`Failed to fetch subtask steps: ${res.status}`);\n\n// after\nconst res = await fetch(`${base}?${params.toString()}`);\nif (!res.ok) {\n  if (res.status === 404 || res.status === 403) return []; // task gone / no access\n  throw new Error(`Failed to fetch subtask steps: ${res.status}`);\n}","handlingStrategy":"try-catch","validationCode":"function validEventQuery(taskId: string, afterSeq?: number): boolean {\n  return taskId.length > 0 && (afterSeq === undefined || Number.isSafeInteger(afterSeq) && afterSeq >= 0);\n}","typeGuard":"export function isSubtaskStepsError(e: unknown): e is Error {\n  return e instanceof Error && e.message.startsWith('Failed to fetch subtask steps:');\n}","tryCatchPattern":"try {\n  return await fetchSubtaskSteps(taskId);\n} catch (e) {\n  if (isSubtaskStepsError(e)) {\n    const status = Number(e.message.split(': ')[1]);\n    if (status === 404 || status === 403) return []; // gone / no access\n    return retryOnce(() => fetchSubtaskSteps(taskId));\n  }\n  throw e;\n}","preventionTips":["Treat 404/403 as empty result, not an error","Verify thread existence before opening the subtask panel","Keep pagination cursor (after_seq) monotonic to avoid refetch loops"],"tags":["tasks","events","pagination","http","frontend"],"backgroundTag":null,"analyzedSha":"1dd6ba1acb03700589994b0366c5d1c7d05e2eff","analyzedAt":"2026-08-14T21:20:34.804Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}