{"record":{"id":"067d203a414605f8","repo":"sickn33/agentic-awesome-skills","slug":"payment-failed","errorCode":null,"errorMessage":"Payment failed","messagePattern":"Payment failed","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"skills/fp-async/SKILL.md","lineNumber":152,"sourceCode":"\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?\n            await refundPayment(payment.id)\n            throw e\n          }\n        } catch (e) {\n          throw e\n        }\n      } catch (e) {\n        throw e\n      }\n    } catch (e) {\n      throw e\n    }","sourceCodeStart":134,"sourceCodeEnd":170,"githubUrl":"https://github.com/sickn33/agentic-awesome-skills/blob/58d857988fcfac6986206bca2b2fe223aa437e4b/skills/fp-async/SKILL.md#L134-L170","documentation":"Illustrative domain error from the payment step of processOrder: chargePayment returned { success: false } and the guard throws 'Payment failed'. In the BEFORE shape this leaves the worst ambiguity — inventory may be reserved and the next try block must guess whether to refund or log.","triggerScenarios":"Card declined by the processor; insufficient funds; gateway timeout after an uncertain capture; amount/currency mismatch causing processor rejection.","commonSituations":"Sandbox/test card numbers used against production gateways; expired stored payment methods; gateway outages; naive retries double-charging when the first attempt actually succeeded.","solutions":["Log the payment processor's decline code — the generic 'Payment failed' message hides the real reason","Make chargePayment idempotent with an idempotency key so retries are safe","Sequence compensation explicitly (refund on shipment failure) instead of nested catch blocks — or use the skill's TaskEither pipeline with explicit rollback in error paths","Validate the payment method (expiry, billing info) before charging"],"exampleFix":"// before\nconst payment = await chargePayment(user, order.total)\nif (!payment.success) throw new Error('Payment failed')\n// after\npipe(\n  chargePaymentTask(user, order.total),\n  TE.chain(payment => payment.success\n    ? TE.right(payment)\n    : TE.left(Object.assign(\n        new Error('Payment failed'),\n        { code: payment.declineCode }\n      )))\n)","handlingStrategy":"retry","validationCode":"// pre-charge validation\nif (!user.paymentMethod || user.paymentMethod.expiry < new Date())\n  return { kind: 'InvalidPaymentMethod' }","typeGuard":"const isPaymentResult = (r: unknown): r is { success: boolean; declineCode?: string } =>\n  typeof r === 'object' && r !== null && typeof (r as any).success === 'boolean'","tryCatchPattern":"try {\n  const payment = await chargePayment(user, order.total)\n  if (!payment.success) throw Object.assign(new Error('Payment failed'), { code: payment.declineCode })\n} catch (e) {\n  // compensating action: release reserved inventory, then rethrow or queue retry\n  await releaseInventory(order.items)\n  throw e\n}","preventionTips":["Send an idempotency key on every charge request","Never retry blindly — only on gateway timeouts with idempotency in place","Implement explicit compensation (refund/release) for each step that already mutated state"],"tags":["documentation","domain-error","payment","compensation"],"backgroundTag":"payment-declined","analyzedSha":"58d857988fcfac6986206bca2b2fe223aa437e4b","analyzedAt":"2026-08-26T11:55:59.350Z","schemaVersion":2},"datasetVersion":"2026-08-26T14:46:13.012Z"}