{"record":{"id":"1c9a6bf48c4919d1","repo":"sickn33/agentic-awesome-skills","slug":"failed-to-fetch-posts-error","errorCode":null,"errorMessage":"Failed to fetch posts: ${error}","messagePattern":"Failed to fetch posts: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"skills/fp-refactor/SKILL.md","lineNumber":183,"sourceCode":"    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  }\n}\n\n// Complex orchestration with try-catch\nasync function getUserWithPosts(id: string): Promise<{ user: User; posts: Post[] } | null> {\n  try {\n    const user = await fetchUser(id);\n    const posts = await fetchUserPosts(id);\n    return { user, posts };\n  } catch (error) {\n    console.error(error);\n    return null;\n  }\n}\n```\n\n#### After (fp-ts TaskEither)\n","sourceCodeStart":165,"sourceCodeEnd":201,"githubUrl":"https://github.com/sickn33/agentic-awesome-skills/blob/58d857988fcfac6986206bca2b2fe223aa437e4b/skills/fp-refactor/SKILL.md#L165-L201","documentation":"The wrapper catch in fetchUserPosts from fp-refactor: any error from the posts request (status throw, network failure, JSON parse failure) is re-thrown with the 'Failed to fetch posts' prefix, obscuring the original cause — the exact anti-pattern the skill refactors.","triggerScenarios":"Any exception while fetching /api/users/:id/posts, including the HTTP error throw two lines above, offline fetch rejection, or invalid JSON in a 200 response.","commonSituations":"Feed widgets failing silently behind a generic banner; log aggregation counting all causes as one error; nested wrappers producing 'Failed to fetch posts: Error: HTTP error: 500' strings.","solutions":["Read the suffix of the message — it contains the inner error that actually matters","Replace message-wrapping with { cause } chaining or Either-tagged errors","Treat 404 on posts as empty data rather than an exception where product-appropriate"],"exampleFix":"// before\ncatch (error) { throw new Error(`Failed to fetch posts: ${error}`) }\n\n// after\ncatch (error) {\n  throw new Error('Failed to fetch posts', { cause: error })\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await fetchUserPosts(userId)\n} catch (e) {\n  const inner = /Failed to fetch posts: (.*)/.exec(String(e))?.[1] ?? String(e)\n  // branch on inner cause\n}","preventionTips":["Prefer error.cause chaining over message-string wrapping","Alert on the inner error, not the wrapper"],"tags":["error-wrapping","async","fetch","debugging"],"backgroundTag":"wrapped-exception-cause-loss","analyzedSha":"58d857988fcfac6986206bca2b2fe223aa437e4b","analyzedAt":"2026-08-26T11:55:59.350Z","schemaVersion":2},"datasetVersion":"2026-08-26T14:46:13.012Z"}