sickn33/agentic-awesome-skills · info · Error
HTTP ${response.status}
Error message
HTTP ${response.status} What it means
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.
Source
Thrown at skills/fp-async/SKILL.md:47
```typescript
// TaskEither<Error, User> means:
// "An async operation that either fails with Error or succeeds with User"
```
---
## 1. Wrapping Promises Safely
### The Problem: Try/Catch Everywhere
```typescript
// BEFORE: Try/catch hell
async function getUserData(userId: string) {
try {
const response = await fetch(`/api/users/${userId}`)
if (!response.ok) {
throw new Error(`HTTP ${response.status}`)
}
const user = await response.json()
try {
const posts = await fetch(`/api/users/${userId}/posts`)
if (!posts.ok) {
throw new Error(`HTTP ${posts.status}`)
}
const postsData = await posts.json()
return { user, posts: postsData }
} catch (postsError) {
// Now what? Return partial data? Rethrow? Log?
console.error('Failed to fetch posts:', postsError)
return { user, posts: [] }
}
} catch (error) {
// Lost all context about what failed
console.error('Something failed:', error)View on GitHub (pinned to 58d857988f)
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
Example fix
// before
if (!response.ok) throw new Error(`HTTP ${response.status}`)
// after
const fetchJson = <T>(url: string): TE.TaskEither<Error, T> =>
TE.tryCatch(
async () => {
const r = await fetch(url)
if (!r.ok) throw new Error(`HTTP ${r.status}: ${r.statusText}`)
return r.json()
},
E.toError
) Defensive patterns
Strategy: try-catch
Validate before calling
const res = await fetch(url)
if (!res.ok) {
const body = await res.text().catch(() => '')
throw new Error(`HTTP ${res.status} ${res.statusText}: ${body.slice(0, 200)}`)
} Type guard
const isHttpError = (e: unknown): e is Error & { status?: number } =>
e instanceof Error && /HTTP \d{3}/.test(e.message) Try / catch
try {
const user = await fetchJson(url)
} catch (e) {
if (e instanceof TypeError) { /* network failure */ }
else { /* HTTP status failure: parse status from message */ }
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
AI-assisted analysis of sickn33/agentic-awesome-skills@58d857988f (2026-08-26).
Data as JSON: /api/errors/0c1be2dfae2ebfe9.
Report an issue: GitHub.