{"record":{"id":"0c1be2dfae2ebfe9","repo":"sickn33/agentic-awesome-skills","slug":"http-response-status","errorCode":null,"errorMessage":"HTTP ${response.status}","messagePattern":"HTTP \\$\\{response\\.status\\}","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"info","filePath":"skills/fp-async/SKILL.md","lineNumber":47,"sourceCode":"\n```typescript\n// TaskEither<Error, User> means:\n// \"An async operation that either fails with Error or succeeds with User\"\n```\n\n---\n\n## 1. Wrapping Promises Safely\n\n### The Problem: Try/Catch Everywhere\n\n```typescript\n// BEFORE: Try/catch hell\nasync function getUserData(userId: string) {\n  try {\n    const response = await fetch(`/api/users/${userId}`)\n    if (!response.ok) {\n      throw new Error(`HTTP ${response.status}`)\n    }\n    const user = await response.json()\n\n    try {\n      const posts = await fetch(`/api/users/${userId}/posts`)\n      if (!posts.ok) {\n        throw new Error(`HTTP ${posts.status}`)\n      }\n      const postsData = await posts.json()\n      return { user, posts: postsData }\n    } catch (postsError) {\n      // Now what? Return partial data? Rethrow? Log?\n      console.error('Failed to fetch posts:', postsError)\n      return { user, posts: [] }\n    }\n  } catch (error) {\n    // Lost all context about what failed\n    console.error('Something failed:', error)","sourceCodeStart":29,"sourceCodeEnd":65,"githubUrl":"https://github.com/sickn33/agentic-awesome-skills/blob/58d857988fcfac6986206bca2b2fe223aa437e4b/skills/fp-async/SKILL.md#L29-L65","documentation":"This is not a runtime error from a library; it is an illustrative throw inside the BEFORE (anti-pattern) example in skills/fp-async/SKILL.md. It shows the common pattern of manually checking response.ok after fetch() and throwing a generic Error with only the HTTP status code. The skill uses it to motivate replacing ad-hoc try/catch nesting with fp-ts TaskEither.","triggerScenarios":"Running the sample code against an endpoint that returns any non-2xx status (404, 500, 401) for GET /api/users/:userId; fetch() itself does not throw on HTTP error statuses, so the manual !response.ok check is the only thing that raises this.","commonSituations":"Developers copying the skill's BEFORE snippet into real code; API base URL misconfigured so every request 404s; missing auth header producing 401; server down returning 5xx; proxy returning 502.","solutions":["Inspect response.status (log the body too) to find the real HTTP problem before blaming the code","Check the URL, method, and headers of the fetch call against the API contract","Use the skill's AFTER pattern: wrap fetch in TE.tryCatch so errors flow through TaskEither instead of nested throws","Distinguish retryable statuses (5xx, 429) from permanent ones (4xx) in your handler"],"exampleFix":"// before\nif (!response.ok) throw new Error(`HTTP ${response.status}`)\n// after\nconst fetchJson = <T>(url: string): TE.TaskEither<Error, T> =>\n  TE.tryCatch(\n    async () => {\n      const r = await fetch(url)\n      if (!r.ok) throw new Error(`HTTP ${r.status}: ${r.statusText}`)\n      return r.json()\n    },\n    E.toError\n  )","handlingStrategy":"try-catch","validationCode":"const res = await fetch(url)\nif (!res.ok) {\n  const body = await res.text().catch(() => '')\n  throw new Error(`HTTP ${res.status} ${res.statusText}: ${body.slice(0, 200)}`)\n}","typeGuard":"const isHttpError = (e: unknown): e is Error & { status?: number } =>\n  e instanceof Error && /HTTP \\d{3}/.test(e.message)","tryCatchPattern":"try {\n  const user = await fetchJson(url)\n} catch (e) {\n  if (e instanceof TypeError) { /* network failure */ }\n  else { /* HTTP status failure: parse status from message */ }\n}","preventionTips":["Always check response.ok; fetch never throws for HTTP errors","Include status and a body snippet in thrown messages","Wrap fetch once in a shared helper instead of per-callsite checks"],"tags":["documentation","fetch","http-status","fp-ts"],"backgroundTag":"fetch-non-2xx-response","analyzedSha":"58d857988fcfac6986206bca2b2fe223aa437e4b","analyzedAt":"2026-08-26T11:55:59.350Z","schemaVersion":2},"datasetVersion":"2026-08-26T14:46:13.012Z"}