Error Handling और Message Normalization

PayCal सभी frontend modules में error reporting को standardize करता है ताकि users को meaningful, secure और consistent error feedback मिले बिना sensitive details expose किए।

Overview और उद्देश्य

जब users errors देखते हैं, उन्हें साफ feedback मिलना चाहिए कि क्या हुआ और कैसे ठीक करना है। Raw backend error messages को normalize किया जाता है ताकि:

  • Noise हटे: redundant "Error:" prefixes और whitespace साफ हों
  • Leakage रुके: sensitive implementation details user तक न पहुंचें
  • Fallbacks मिलें: empty या malformed errors पर safe messages दिखें
  • Consistency रहे: सभी 11+ frontend modules में वही logic लागू हो
  • Debugging सुधरे: full details Phantom Wing में log हों और users को safe summaries दिखें

Problem: Generic बनाम meaningful errors

Standardization से पहले PayCal modules ad-hoc error handling इस्तेमाल करते थे:

// ❌ BAD: Exposes raw error, duplicates logic
PC.showToast(error?.message || 'Import failed.');
PW.error(`Import failed: ${error.message}`);

इस approach की समस्याएं:

  • Users को "ECONNREFUSED: Connection refused" जैसे confusing raw messages दिखते हैं
  • हर module अपनी fallback logic अलग से बनाता है
  • Whitespace trimming या prefix stripping consistent नहीं थी
  • Empty errors UI में "undefined" की तरह दिख सकते थे

Solution: Standardized Error Resolver

सभी PayCal frontend modules अब एक unified resolver function इस्तेमाल करते हैं जो error messages normalize करता है:

// ✅ GOOD: Normalized, consistent, safe
const resolveThrownMessage = (error, fallbackMessage) => {
  const raw = typeof error?.message === 'string' 
    ? error.message 
    : String(error || '');
  const normalized = raw.replace(/^Error:\s*/i, '').trim();
  return normalized !== '' ? normalized : fallbackMessage;
};

Usage:

// In catch blocks across modules
try {
  await updateProfile(data);
} catch (error) {
  const message = resolveThrownMessage(error, 'Unable to update profile.');
  PC.showToast(message, 'error');  // User sees meaningful feedback
  PW.error(message);                // Logged for debugging
}

Implementation Scope

April 2026 तक यह standardized pattern 11 frontend modules और लगभग 40+ normalized catch blocks में लागू है:

Authentication और Settings (7 modules)

  • html/js/auth-recovery/index.php (4 catches)
  • html/js/signin/index.php (2 catches)
  • html/js/signin/verification-reminder.js (2 catches)
  • html/js/signin/verification-status-banner.js (1 catch)
  • html/js/settings/index.php (8+ catches)

Core और Data Modules (4 modules)

  • html/js/core/network.js (3 catches)
  • html/js/core/index.php (5 catches)
  • html/js/core/billing.js (5 catches)
  • html/js/earnings/index.php (4 catches)

High-value modules (10+ catch points):

  • html/js/organizations/index.php - Org management, access requests, audit trails (19+ catches)
  • html/js/sites/index.php - Site CRUD, earnings, orphan work recovery (10+ catches)
  • html/js/calendar/calendar.js - Day-entry operations, copy/paste/delete (2 catches)

Error Categories और Handling Patterns

Resolver कई error categories में consistently लागू होता है:

1. Network Request Failures

// Network module: HTTP errors, timeouts, connection issues
async function deleteResource(ep, id) {
  try {
    // ...fetch logic...
  } catch (error) {
    const resolved = resolveThrownMessage(error, 'Network error');
    const msg = `[deleteResource] ${resolved}`;
    PW.error(msg);
    throw new Error(msg);
  }
}

2. API Response Handling

// Billing/Settings: Server returned error message in payload
try {
  const response = await fetch('/api/v1/billing/subscription');
  const payload = await response.json();
  if (!response.ok) {
    throw new Error(payload?.message || 'Unable to load billing status.');
  }
} catch (error) {
  const resolved = resolveThrownMessage(error, 'Unable to load billing status.');
  setScreenReaderStatus(resolved);
}

3. UI Operation Failures

// Calendar/Organizations: User-initiated actions (paste, delete, update)
button.addEventListener('click', async () => {
  try {
    await performAction();
    PC.showToast('Success!', 'save');
  } catch (error) {
    const message = resolveThrownMessage(error, 'Action failed. Try again.');
    PC.showToast(message, 'error');
  }
});

4. Async Initialization

// Core modules: Startup or dependent initialization failures
try {
  NavigationToggle.init();
} catch (err) {
  const resolved = resolveThrownMessage(err, 'Navigation init failed');
  PW.warn(resolved);  // Logged but doesn't block page
}

Security Considerations

Error message normalization user privacy और system integrity को protect करता है:

  • No Database Details: "UNIQUE constraint failed on email" जैसे backend errors API boundary पर intercept होकर user-friendly messages बनते हैं
  • No File Paths: file paths या process details expose करने वाले system errors हटाए जाते हैं
  • No Auth Leakage: authentication failures कभी नहीं बताते कि account exists करता है या नहीं
  • No CORS/Network Details: transport errors generic connection messages में normalize होते हैं
  • Secure Fallbacks: हर catcher में explicit fallback है; "undefined" या "null" नहीं दिखता

User Experience Benefits

यह standardization users को clearer, safer और more consistent feedback देता है और support/debugging को आसान बनाता है।

  • Messages implementation detail expose किए बिना समझ आते हैं
  • Backend error missing या malformed होने पर fallback safe रहता है
  • Logging debugging के लिए useful रहता है बिना sensitive values UI में leak किए

Debugging और Support Workflow

Support team consistent resolver path पर भरोसा कर सकती है और जरूरत पड़ने पर Phantom Wing logs में full technical detail देख सकती है।

  • User normalized message देखता है
  • Phantom Wing full error context privately record करता है
  • Support raw backend response expose किए बिना issue class correlate कर सकता है

Testing और Quality Assurance

Normalization logic focused module tests और main frontend flows के integration checks से cover है।

Maintenance और Future Extensions

PayCal जैसे-जैसे modules जोड़ता है, custom error formatting duplicate करने के बजाय यही resolver pattern reuse होना चाहिए।

  • New modules shared resolver को directly call करें
  • Module-specific fallback messages concise और user-facing रहें
  • Resolver changes representative flows में regression-tested हों

इससे codebase बढ़ने पर behavior predictable रहता है और module-specific error handling की दूसरी generation नहीं बनती।

Summary: PayCal Error-Handling Standard

PayCal ने frontend error handling standardize किया ताकि users को safe, consistent messages मिलें और developers को debugging के लिए जरूरी information मिलती रहे।

  • Display से पहले error messages normalize करें
  • Implementation details users से छिपाएं
  • Empty या malformed errors के लिए explicit fallback text इस्तेमाल करें
  • Support और debugging के लिए technical detail privately log करें