{"record":{"id":"fce15f4e65597d36","repo":"sickn33/agentic-awesome-skills","slug":"http-error-response-status","errorCode":null,"errorMessage":"HTTP error: ${response.status}","messagePattern":"HTTP error: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"skills/fp-refactor/SKILL.md","lineNumber":166,"sourceCode":"### Step-by-Step Refactoring Guide\n\n1. **Identify the error type**: Determine what errors can occur and create appropriate error types\n2. **Change return type**: From `T` to `Either<E, T>` where `E` is your error type\n3. **Replace throw statements**: Convert `throw new Error(...)` to `E.left(new Error(...))`\n4. **Replace return statements**: Convert `return value` to `E.right(value)`\n5. **Remove try-catch blocks**: They're no longer needed\n6. **Update callers**: Use `pipe` with `E.flatMap` to chain operations\n\n### Pattern: Async try-catch to TaskEither\n\n#### Before (Imperative)\n\n```typescript\nasync function fetchUser(id: string): Promise<User> {\n  try {\n    const response = await fetch(`/api/users/${id}`);\n    if (!response.ok) {\n      throw new Error(`HTTP error: ${response.status}`);\n    }\n    const data = await response.json();\n    return validateUser(data);\n  } catch (error) {\n    throw new Error(`Failed to fetch user: ${error}`);\n  }\n}\n\nasync function fetchUserPosts(userId: string): Promise<Post[]> {\n  try {\n    const response = await fetch(`/api/users/${userId}/posts`);\n    if (!response.ok) {\n      throw new Error(`HTTP error: ${response.status}`);\n    }\n    return await response.json();\n  } catch (error) {\n    throw new Error(`Failed to fetch posts: ${error}`);\n  }","sourceCodeStart":148,"sourceCodeEnd":184,"githubUrl":"https://github.com/sickn33/agentic-awesome-skills/blob/58d857988fcfac6986206bca2b2fe223aa437e4b/skills/fp-refactor/SKILL.md#L148-L184","documentation":"In fp-refactor's fetchUser, this throws when the GET /api/users/:id response has ok === false, before JSON parsing. The skill contrasts this try/catch tower with a composed pipeline using TaskEither.","triggerScenarios":"fetch to /api/users/:id returning 401/403/404/500 — wrong id, expired session, or server error.","commonSituations":"Auth cookie/token expired between page load and API call; reverse proxy returning 502 while backend restarts; id typos from user-entered values.","solutions":["Check the status code in the thrown message and fix the corresponding cause (re-auth for 401, verify id for 404)","Centralize fetch with interceptors that refresh tokens and retry once","Refactor to TE.chain pipelines so status errors flow as Left values with context"],"exampleFix":"// before\nconst response = await fetch(`/api/users/${id}`)\nif (!response.ok) throw new Error(`HTTP error: ${response.status}`)\n\n// after\nconst httpGet = (url: string) =>\n  TE.tryCatch(async () => {\n    const r = await fetch(url)\n    if (!r.ok) throw Object.assign(new Error(`HTTP ${r.status}`), { status: r.status })\n    return r.json()\n  }, E.toError)","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await fetchUser(id)\n} catch (e) {\n  const m = /HTTP error: (\\d+)/.exec(String(e))\n  if (m) switch (m[1]) {\n    case '401': /* re-auth */ break\n    case '404': /* render not-found */ break\n    default: throw e\n  }\n}","preventionTips":["Use a central fetch wrapper that throws typed status errors","Refresh tokens proactively to avoid 401 mid-session"],"tags":["http","fetch","async","network"],"backgroundTag":"http-error-status","analyzedSha":"58d857988fcfac6986206bca2b2fe223aa437e4b","analyzedAt":"2026-08-26T11:55:59.350Z","schemaVersion":2},"datasetVersion":"2026-08-26T14:46:13.012Z"}