ðĄïļ ERROR_HANDLING.md - Error Handling & Resilience Strategy (āļāļĨāļĒāļļāļāļāđāļāļēāļĢāļāļąāļāļāļēāļĢāļāđāļāļāļīāļāļāļĨāļēāļāđāļĨāļ°āļāļ§āļēāļĄāļĒāļ·āļāļŦāļĒāļļāđāļāļĢāļ°āļāļ)
This document details SplitDeeâs resilience patterns, expected system failure modes, recovery paths, and exception handling protocols.
āđāļāļāļŠāļēāļĢāļāļāļąāļāļāļĩāđāđāļŠāļāļāđāļāļāļāļąāļāļĢāļ°āļāļāļāļ§āļēāļĄāļāļāļāļēāļāļāļāļ SplitDee, āļāļĢāļ°āđāļ āļāļāđāļāļāļīāļāļāļĨāļēāļāļāļĩāđāļāļēāļāđāļāļīāļāļāļķāđāļ āđāļāļ§āļāļēāļāļāļđāđāļāļ·āļāļĢāļ°āļāļ āđāļĨāļ°āļĢāļ°āđāļāļĩāļĒāļāļāļāļīāļāļąāļāļīāđāļāļāļēāļĢāđāļāđāļāļāđāļāļĒāļāđāļ§āđāļāļāļēāļāđāļāļāļāļīāļ
ðđð āļ āļēāļĐāļēāđāļāļĒ (āļŠāļģāļŦāļĢāļąāļāļāļđāđāđāļāđāļāļēāļ)
1. āļĢāļēāļĒāļāļēāļĢāļāđāļāļāļīāļāļāļĨāļēāļāļāļĩāđāļāļēāļāļāļēāļĢāļāđāđāļĨāļ°āđāļāļāļāļēāļĢāļāļđāđāļāļ·āļ (Expected Failures & Recovery)
- āļĢāļ°āļāļāđāļŠāļāļāđāļāđāļāļĒāļāļāļŠāļĨāļīāļāļāļāļēāļāļēāļĢāļ āļēāļĒāļāļāļāļĨāđāļĄ/āļŦāļĄāļāđāļ§āļĨāļē:
- āļāļąāļāļŦāļē: āļĢāļ°āļāļāļ āļēāļĒāļāļāļ (āđāļāđāļ SlipOK) āļāļāļāļāļĨāļąāļāļŦāļĄāļāđāļ§āļĨāļē 504 āļŦāļĢāļ·āļāļāļēāļāļāļēāļĢāđāļāļ·āđāļāļĄāļāđāļ
- āļāļēāļĢāļāļđāđāļāļ·āļ: āļŦāļĨāļąāļāļāđāļēāļāđāļāļāļāļ°āđāļĄāđāđāļāļĢāļāļĨāđāļĄāđāļŦāļĨāļ§ āļāļģāļāļēāļĢāļāļąāļāļāļķāļāļāļĢāļ°āļ§āļąāļāļīāđāļāđāļ âāļĢāļāļāļĢāļ§āļāļŠāļāļāļāđāļ§āļĒāļāļēāđāļāļĨāđāļēâ (
pending_manual) āļāđāļēāļāļŠāļāļēāļāļ°āļŦāļāļĩāđāļĨāļđāļāļŦāļāļĩāđāđāļ§āđāđāļāđāļāļĢāļ°āļŦāļ§āđāļēāļāļāļĢāļ§āļāļŠāđāļĨāļāđ (processing) āđāļāđāļāļĨāļđāļāļŦāļāļĩāđāđāļŦāđāļ§āļēāļāđāļāļĒāļāļāđāļāđāļĢāļąāļāļŠāđāļāļāđāļĨāđāļ§ āđāļĨāļ°āļĒāļīāļāļ āļēāļĢāļāļīāļāļāļĢāļ§āļāđāļāļ Statement āļŠāđāļāļāļķāļāđāļāđāļēāļŦāļāļĩāđāđāļāļ·āđāļāļāļāļĒāļ·āļāļĒāļąāļāļāđāļ§āļĒāļĄāļ·āļāđāļāļĨāđāļē
- āļāļēāļĢāļāļģāļŠāļĨāļīāļāđāļāđāļēāļĄāļēāđāļŠāļāļāđāļāļāļāđāļģāļŠāļāļāļĢāļāļ (Duplicate Slip / Double-Spending):
- āļāļąāļāļŦāļē: āļāļđāđāđāļāđāļāļēāļāļŠāđāļāļŠāļĨāļīāļāđāļāļīāļĄāļāļĩāđāļāļĢāļ§āļāļāļĢāļ°āļ§āļąāļāļīāļāđāļēāļāđāļāđāļĨāđāļ§ āļŦāļ§āļąāļāđāļāļĨāļĩāļĒāļĢāđāļāļīāļĨāļŦāļēāļĢāđāļāļīāļāđāļāđāļŦāļĄāđ
- āļāļēāļĢāļāļđāđāļāļ·āļ: āļāļĢāļ§āļāļĢāļŦāļąāļŠāļāļļāļĢāļāļĢāļĢāļĄāļāļēāļĢāđāļāļāļāļāļāļāļāļēāļāļēāļĢāļāļāļāļąāļāļĢāļ°āļāļāļāļąāļāļāļĩāļāļĩāļĒāđāļāļģāļāļąāļāļŦāđāļēāļĄāļāđāļģ (
slip_trans_id) āđāļāļŠāļāđāđāļāļĢāļāļ°āđāļĄāđāļĒāļāļĄāđāļŦāđāđāļāļĩāļĒāļāđāļāļ§āļāļĢāļ°āļ§āļąāļāļīāļāđāļģ āđāļĨāļ°āļĒāļīāļāđāļāļ·āļāļāļāļđāđāļŠāđāļāļāļ·āļāļĒāļāļāļ§āđāļē âāļŠāļĨāļīāļāļāļĩāđāļāļđāļāđāļāđāļĒāļ·āļāļĒāļąāļāļĒāļāļāđāļāļīāļāđāļāđāļĨāđāļ§â āđāļĨāļ°āļāļĩāļāļŠāđāļāļāļąāļŠāļāļĨāļąāļāđāļāđāļāļĒāļąāļāđāļĄāđāļāđāļēāļĒāļāļąāļāļāļĩ
- āļŠāđāļāļāļĢāļđāļāļāļīāļ§āļāļēāļĢāđāļāļĢāđāļāļĄāđāļāļĒāđāļāļĩāđāļāļāļāđāļ§āđāļāļēāļāļāļāļĨāđāļēāļŦāļĨāļąāļāļŦāļĄāļāļāļēāļĒāļļ:
- āļāļąāļāļŦāļē: āļŠāļĄāļēāļāļīāļāļĢāļ·āđāļāļāļīāļ§āļāļēāļĢāđāļāļĢāđāļāļĄāđāļāļĒāđāđāļāđāļāđāļēāļĄāļēāļāđāļāļāļŦāļāđāļēāļāļĩāđ āļāļķāđāļāļāļīāļĨāļĄāļĩāļāļēāļĢāđāļāđāđāļāļāļĢāļąāļāļāļĢāļļāļāļāđāļāļĄāļđāļĨāļŦāļāļĩāđāļŠāļīāļāļŦāļĢāļ·āļāļāļđāļāļāļđāđāļŠāļĢāđāļēāļāļĨāļāđāļāđāļĨāđāļ§
- āļāļēāļĢāļāļđāđāļāļ·āļ: āđāļĄāđāđāļāļīāļāļāļ°āđāļāđāļēāļāļāļēāļāļēāļĢ āđāļāđāđāļ§āļĨāļēāļāļąāļāđāļŦāļĨāļāļĢāļ°āļāļāļāļ°āļŠāđāļāļāļ§āļąāļāđāļĨāļ°āđāļ§āļĨāļēāļāļĢāļīāļāļāļāļāļāļāļēāļāļēāļĢāļĄāļēāđāļāđāļāđāļāļĩāļĒāļāļāļąāļāđāļ§āļĨāļēāļāļĢāļąāļāļāļĢāļļāļāļŠāđāļāļāļāļīāļĨāļŦāļĨāļąāļāļāđāļēāļ āļŦāļēāļāļāļĢāļ§āļāļāļāļ§āđāļēāđāļāļāļāđāļāļāļāļąāļāđāļāļāđāļāđāļĒāļāļāļŦāļāļĩāđāļāļĢāļīāļ āļāļ°āļāļģāļāļēāļĢāļŠāđāļāļāļāļīāđāļŠāļāļŠāļĨāļīāļāļāļąāđāļāđāļĨāļ°āļāļąāđāļāļāđāļēāđāļāđāļ āļĒāļāļāđāļĄāđāļāļĢāļ āļŦāļĢāļ·āļ āļŠāļĨāļīāļāļŦāļĄāļāļāļēāļĒāļļāļāļēāļĢāđāļāđāļāļēāļ
2. āļāļēāļĢāļāļ§āļāļāļļāļĄāļāļ§āļēāļĄāļāļĨāļāļāļ āļąāļĒāļāđāļāļāļāļąāļāļĢāļēāļĒāļāļēāļĢāļĢāļąāļāļāļĢāđāļāļĄāļāļąāļ (Concurrency & Race Condition)
- āļĨāļđāļāļŦāļāļĩāđāļŠāđāļāļŠāļĨāļīāļāļĢāļąāļ§āļāļļāđāļĄāļāļĢāđāļāļĄāđ āļāļąāļ:
- āļāļēāļĢāļāļđāđāļāļ·āļ: āļĢāļ°āļāļąāļāđāļāļŠāļĄāļĩāļāļēāļĢāļēāļāļāļĩāļĒāđāļāļļāļĄāļŠāļąāļāļŠāđāļ§āļāļŠāđāļ§āļāļŦāļāļĩāđāđāļāļĩāđāļĒāļ§ āđāļĨāļ°āļĢāļ°āļāļąāļāđāļāđāļāļŦāļĨāļąāļāļāđāļēāļāļĄāļĩāļāļąāļ§āļĄāļąāļāļĨāđāļāļāļāļąāđāļ§āļāļĢāļēāļ§āļāđāļēāļ Redis (
lock_key) āļāļąāļ§āļĨāđāļāļāļāļ°āļāļĨāļēāļĒāļāļāļāļāđāļāđāļĄāļ·āđāļāļāļąāđāļāļāļāļāļāļēāļĢāļāļĢāļ°āļĄāļ§āļĨāļāļĨāđāļāļāđāļŠāļĢāđāļāļŠāļīāđāļ āđāļāļ·āđāļāđāļĄāđāđāļŦāđāđāļāļĢāļāļāđāļāļĄāļđāļĨāļāļēāļĢāđāļāļāļāļāļāļąāļ
- āļāļēāļĢāļāļđāđāļāļ·āļ: āļĢāļ°āļāļąāļāđāļāļŠāļĄāļĩāļāļēāļĢāļēāļāļāļĩāļĒāđāļāļļāļĄāļŠāļąāļāļŠāđāļ§āļāļŠāđāļ§āļāļŦāļāļĩāđāđāļāļĩāđāļĒāļ§ āđāļĨāļ°āļĢāļ°āļāļąāļāđāļāđāļāļŦāļĨāļąāļāļāđāļēāļāļĄāļĩāļāļąāļ§āļĄāļąāļāļĨāđāļāļāļāļąāđāļ§āļāļĢāļēāļ§āļāđāļēāļ Redis (
- āļāļēāļĢāđāļāļĩāļĒāļāļāļēāļĢāļēāļāļāđāļāļĄāļđāļĨāļĨāđāļĄāđāļŦāļĨāļ§āļāļĨāļēāļāļāļąāļ:
- āļāļēāļĢāļāļđāđāļāļ·āļ: āļŦāđāļāļŦāļļāđāļĄāļāļģāļŠāļąāđāļāļāļēāļĢāļŦāļēāļĢāļāļĢāļ°āļĄāļ§āļĨāļāļĨāđāļ§āđāđāļāđ Database Transaction āļāđāļāļāđāļāļĩāļĒāļ§āļāļąāļ āļŦāļēāļāđāļāļīāļāļāļ§āļēāļĄāļāļīāļāļāļĨāļēāļāđāļāđ āļāļĨāļēāļāļāļąāļ (āđāļāđāļ āļŦāļąāļ XP āļāļāļŦāļĨāđāļ) āļĢāļ°āļāļāļāļ°āļāļāļĒāļāđāļĨāļīāļāļāļēāļĢāļāļąāļāļāļķāļāļĒāđāļāļāļŦāļĨāļąāļ (Rollback) 100% āđāļāļ·āđāļāļĢāļąāļāļĐāļēāļĢāļ°āļāļąāļāļāđāļāļĄāļđāļĨāļŠāļēāļāļĨāđāļŦāđāļŠāļĄāļāļđāļĢāļāđ
3. āļāļĪāļāļīāļāļĢāļĢāļĄāđāļĄāļ·āđāļāļĄāļ·āļāļāļ·āļāđāļĄāđāļĄāļĩāđāļāđāļ (Offline Mode)
- āļāļēāļĢāļāđāļēāļāļāļĢāļ°āļ§āļąāļāļī: āđāļāļĢāļĻāļąāļāļāđāļāļ°āļāļķāļāļāļĢāļ°āļ§āļąāļāļīāļāļĨāļļāđāļĄ āļĢāļēāļĒāļĨāļ°āđāļāļĩāļĒāļāļāļīāļĨ āđāļĨāļ°āļŠāđāļāļāļąāļŠāđāļĄāļāļīāļāļēāļāđāļāļāđāļāļĢāļ·āđāļāļāļ āļēāļĒāđāļāđāļŦāđāļāļđāđāđāļāđāļāļđāđāļāđāđāļĄāđāđāļĄāđāļĄāļĩāđāļāđāļ
- āļāļēāļĢāļāļģāļĢāļēāļĒāļāļēāļĢāđāļŦāļĄāđ: āļĢāļ°āļāļāļāļĨāđāļāļāļāļļāđāļĄāđāļāđāļāļēāļāļŠāļĢāđāļēāļāļāļĨāļļāđāļĄ āļŦāļēāļĢāļāļīāļĨ āđāļĨāļ°āđāļŠāļāļāļāļĢāļ§āļāļŠāļĨāļīāļāļāļąāļāļāļĩāļŦāļēāļāļāļāļāđāļĨāļāđ āļāļĢāđāļāļĄāļāļķāđāļāđāļāļ·āļāļ âāļāļĢāļļāļāļēāđāļāļ·āđāļāļĄāļāļīāļāđāļāļāļĢāđāđāļāđāļāđāļāļ·āđāļāļāļģāļĢāļēāļĒāļāļēāļĢâ āđāļāļ·āđāļāļāļ§āļēāļĄāļāļĨāļāļāļ āļąāļĒ
ðŽð§ English (For AI Agents)
1. Expected Failures & Recovery Paths
- Slip Verification API Timeout / Outage
- Failure Scenario: The third-party bank transaction check API (e.g. SlipOK) returns a 504 Gateway Timeout or is completely unreachable.
- Immediate Recovery: The API catches the exception, updates the payment record to
pending_manual, locks the share status asprocessing, informs the debtor, and queues a manual approval card in the creditorâs feed.
- Duplicate Slip / Double-Spending Attempt
- Failure Scenario: A user uploads a slip with a bank transaction ID that has already been verified in the system.
- Handling Protocol: Database level unique constraints on
slip_trans_idreject duplicate rows, HTTP 400 with codeSLIP_ALREADY_USEDis returned to the client, and the share is reset tounpaid.
- Expired PromptPay QR Code
- Failure Scenario: A debtor scans and pays using a PromptPay QR code containing outdated bill split values.
- Handling Protocol: Compare the bank transaction statement timestamp with the bill modification timestamp. If the payment occurred before the last bill update, reject the slip with code
SLIP_AMOUNT_MISMATCHorPAYMENT_EXPIRED.
2. Concurrency & Race Condition Protections
- Concurrent Slip Uploads
- Resolution: Composite database unique constraints on
(bill_id, user_id)andslip_trans_id. Acquire a Redis distributed locklock:share:{share_id}during verification, releasing it only on success or rollback.
- Resolution: Composite database unique constraints on
- Relational Transaction Rollback
- Resolution: Wrap use case actions inside atomic database transactions. Execute rollbacks on any sub-action failure to preserve data integrity.
3. Offline Mode Behavior
- Read Operations: Cached local storage (SQLite/Hive) allows users to view group details, bill history, and Mochiâs status offline.
- Write Operations: Operations like creating groups, publishing bills, or verifying slips are blocked. Show error âInternet connection required to perform this action.â