{"record":{"id":"2a3e3f3e18ce5f10","repo":"sickn33/agentic-awesome-skills","slug":"failed-to-fetch-user-error","errorCode":null,"errorMessage":"Failed to fetch user: ${error}","messagePattern":"Failed to fetch user: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"skills/fp-refactor/SKILL.md","lineNumber":171,"sourceCode":"4. **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  }\n}\n\n// Complex orchestration with try-catch\nasync function getUserWithPosts(id: string): Promise<{ user: User; posts: Post[] } | null> {\n  try {","sourceCodeStart":153,"sourceCodeEnd":189,"githubUrl":"https://github.com/sickn33/agentic-awesome-skills/blob/58d857988fcfac6986206bca2b2fe223aa437e4b/skills/fp-refactor/SKILL.md#L153-L189","documentation":"The catch-all in fp-refactor's fetchUser: any failure inside the try block — the HTTP status throw, network rejection, JSON parse error, or validateUser throwing — is re-wrapped with a 'Failed to fetch user' prefix. This nesting loses the original error class, which the skill uses to argue for error values.","triggerScenarios":"Any exception on the /api/users/:id path: offline network rejection, non-2xx status, malformed JSON body, or payload failing validateUser.","commonSituations":"Wrapping throws in wrapper throws so the root cause is buried; debugging becomes string-matching on message prefixes; monitoring groups unrelated failures under one message.","solutions":["Preserve cause: throw new Error('Failed to fetch user', { cause: error }) instead of string-wrapping","Inspect error.cause / inner message before this wrapper when debugging","Use Either/TaskEither so each step tags its own failure without wrapping"],"exampleFix":"// before\ncatch (error) { throw new Error(`Failed to fetch user: ${error}`) }\n\n// after (preserve cause, ES2022)\ncatch (error) {\n  throw new Error('Failed to fetch user', { cause: error })\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await fetchUser(id)\n} catch (e) {\n  // read e.cause (or the message suffix) for the real failure\n  const cause = (e as Error & { cause?: Error }).cause ?? e\n}","preventionTips":["Wrap errors with { cause } to keep the root error","Group telemetry on inner error class, not wrapper prefix"],"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"}