{"record":{"id":"e4c66f12813b6d70","repo":"sickn33/agentic-awesome-skills","slug":"order-not-found","errorCode":null,"errorMessage":"Order not found","messagePattern":"Order not found","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"skills/fp-async/SKILL.md","lineNumber":140,"sourceCode":"// From a condition\nconst mustBePositive = TE.fromPredicate(\n  (n: number) => n > 0,\n  (n) => new Error(`Expected positive, got ${n}`)\n)\n```\n\n---\n\n## 2. Chaining Async Operations\n\n### The Problem: Callback Hell / Nested Awaits\n\n```typescript\n// BEFORE: Deeply nested, hard to follow\nasync function processOrder(orderId: string) {\n  try {\n    const order = await fetchOrder(orderId)\n    if (!order) throw new Error('Order not found')\n\n    try {\n      const user = await fetchUser(order.userId)\n      if (!user) throw new Error('User not found')\n\n      try {\n        const inventory = await checkInventory(order.items)\n        if (!inventory.available) throw new Error('Out of stock')\n\n        try {\n          const payment = await chargePayment(user, order.total)\n          if (!payment.success) throw new Error('Payment failed')\n\n          try {\n            const shipment = await createShipment(order, user)\n            return { order, shipment, payment }\n          } catch (e) {\n            // Refund payment? Log? What's the state now?","sourceCodeStart":122,"sourceCodeEnd":158,"githubUrl":"https://github.com/sickn33/agentic-awesome-skills/blob/58d857988fcfac6986206bca2b2fe223aa437e4b/skills/fp-async/SKILL.md#L122-L158","documentation":"Illustrative domain error from the processOrder BEFORE example: fetchOrder returned a falsy order (null/undefined), and the guard throws 'Order not found'. It demonstrates how deeply nested try/catch pyramids form when each step validates its own result.","triggerScenarios":"processOrder called with an unknown, deleted, or mis-typed orderId; fetchOrder returning null instead of throwing; a race where the order was removed between lookup and processing.","commonSituations":"Stale IDs from client caches or old links; test fixtures referencing seeded data that was wiped; soft-deleted orders still referenced by other tables.","solutions":["Verify the orderId exists before calling processOrder (preflight lookup or validation)","Check whether fetchOrder should distinguish 'missing' (null) from 'fetch failed' (throw)","Refactor to the skill's AFTER pipeline using TE.fromNullable / TE.fromOption so a missing order becomes a typed Left","Return a discriminated error (e.g. { kind: 'OrderNotFound' }) so callers can branch cleanly"],"exampleFix":"// before\nconst order = await fetchOrder(orderId)\nif (!order) throw new Error('Order not found')\n// after\npipe(\n  TE.tryCatch(() => fetchOrder(orderId), E.toError),\n  TE.chain(order => order == null\n    ? TE.left(new Error('Order not found'))\n    : TE.right(order)),\n  TE.chain(order => fetchUserTask(order.userId)),\n  TE.chain(user => chargePaymentTask(user, order.total))\n)","handlingStrategy":"validation","validationCode":"if (!orderId || typeof orderId !== 'string') throw new TypeError('orderId required')\nconst exists = await orderExists(orderId)\nif (!exists) return { kind: 'OrderNotFound', orderId }","typeGuard":"const isOrder = (o: unknown): o is Order =>\n  typeof o === 'object' && o !== null && 'userId' in o && 'items' in o && 'total' in o","tryCatchPattern":"try {\n  const order = await fetchOrder(orderId)\n  if (!order) return { kind: 'OrderNotFound', orderId }\n} catch (e) {\n  // fetch itself failed — distinct from a missing order\n  throw e\n}","preventionTips":["Separate 'missing' from 'failed' in fetch functions","Validate IDs before dispatch","Return typed result objects instead of throwing for expected absences"],"tags":["documentation","domain-error","null-check","fp-ts"],"backgroundTag":"entity-not-found","analyzedSha":"58d857988fcfac6986206bca2b2fe223aa437e4b","analyzedAt":"2026-08-26T11:55:59.350Z","schemaVersion":2},"datasetVersion":"2026-08-26T14:46:13.012Z"}