|
| 1 | +--- |
| 2 | +name: debug-api |
| 3 | +description: Debug HTTP/network/API failures in mParticle Web SDK including fetch failed/fetch error/request failed/API call failed/endpoint not responding/401 unauthorized/403 forbidden/404 not found/500 internal server error/502 bad gateway/503 service unavailable/504 gateway timeout/network error/timeout/ETIMEDOUT/connection timeout/ECONNREFUSED/response format wrong/DTO mismatch/type mismatch in response/unexpected response/null response/undefined response/empty response/missing data/API contract changed/batch upload failed/identity API failed/config API failed/events API failed |
| 4 | +--- |
| 5 | + |
| 6 | +# API Debug Skill - Web SDK |
| 7 | + |
| 8 | +## Purpose |
| 9 | +Diagnose network/API failures in the mParticle Web SDK through systematic request/response inspection and API client debugging. |
| 10 | + |
| 11 | +## Core Principles |
| 12 | +- **Network tab is truth**: Inspect actual requests, not assumptions |
| 13 | +- **Mock vs real divergence**: fetch-mock works but real API fails → contract drift |
| 14 | +- **Batch timing matters**: Events batched before upload (100 events or 30 seconds) |
| 15 | +- **Three API systems**: Events, Identity, and Config APIs have different shapes |
| 16 | + |
| 17 | +## Architecture Context |
| 18 | +HTTP clients in `src/apiClient.ts` (Events), `src/identityApiClient.ts` (Identity), `src/configAPIClient.ts` (Config). Uses fetch API. Batch upload in `src/batchUploader.ts`. Tests use fetch-mock for HTTP mocking. |
| 19 | + |
| 20 | +## Failure Classification |
| 21 | + |
| 22 | +**Request never sent:** |
| 23 | +- Network offline → browser blocking |
| 24 | +- Batch not full → waiting for 100 events or 30 second interval |
| 25 | +- API client not initialized → SDK init failed |
| 26 | +- Config disabled feature → server config blocking |
| 27 | + |
| 28 | +**Request fails:** |
| 29 | +- 401 → Auth token invalid/expired |
| 30 | +- 403 → Workspace permissions issue |
| 31 | +- 404 → URL wrong (trailing slash, workspace ID, endpoint) |
| 32 | +- 500 → Backend error (check server logs) |
| 33 | +- Timeout → slow network/server hang |
| 34 | +- CORS → should not happen with mParticle APIs (same-origin or configured) |
| 35 | + |
| 36 | +**Response wrong:** |
| 37 | +- DTO mismatch → backend changed contract |
| 38 | +- Null/undefined → optional fields missing |
| 39 | +- Type error → response shape unexpected |
| 40 | +- Empty response → valid but no data |
| 41 | + |
| 42 | +**SDK-specific issues:** |
| 43 | +- Batch upload stuck → timer not advancing |
| 44 | +- Identity callback not fired → response parsing failed |
| 45 | +- Config not loading → initial config fetch failed |
| 46 | +- Events not forwarding → kits not initialized |
| 47 | + |
| 48 | +## Investigation Strategy |
| 49 | + |
| 50 | +### 1. Network Inspection |
| 51 | +Use browser DevTools Network tab: |
| 52 | +- Request URL (exact match with workspace ID) |
| 53 | +- Request headers (Content-Type, User-Agent) |
| 54 | +- Request payload (batch structure, identity request) |
| 55 | +- Response status (200/401/403/404/500) |
| 56 | +- Response body (success flags, error messages) |
| 57 | +- Timing (slow? timeout?) |
| 58 | + |
| 59 | +### 2. API Client State |
| 60 | +Log client state: |
| 61 | +```typescript |
| 62 | +// In apiClient.ts |
| 63 | +console.log({ url, payload, config: mpInstance._Store }) |
| 64 | + |
| 65 | +// In identityApiClient.ts |
| 66 | +console.log({ identityRequest, callback }) |
| 67 | + |
| 68 | +// In batchUploader.ts |
| 69 | +console.log({ batchSize, uploadInterval, queuedEvents }) |
| 70 | +``` |
| 71 | + |
| 72 | +### 3. Verify API Endpoints |
| 73 | +Check endpoint construction: |
| 74 | +- Events: `/v1/[workspace]/events` |
| 75 | +- Identity: `/v1/[workspace]/identify` (or `/login`, `/logout`, `/modify`) |
| 76 | +- Config: `/v1/[workspace]/config` |
| 77 | + |
| 78 | +Ensure workspace ID (devToken/apiKey) is correct. |
| 79 | + |
| 80 | +### 4. fetch-mock vs Real API |
| 81 | +If fetch-mock works but real fails: |
| 82 | +- Compare mock URL vs real endpoint |
| 83 | +- Check mock response shape vs real DTO |
| 84 | +- Verify auth headers match |
| 85 | +- Look for hardcoded test data |
| 86 | + |
| 87 | +## Common Root Causes |
| 88 | + |
| 89 | +**Auth failures:** |
| 90 | +- API key (devToken) missing or wrong |
| 91 | +- API key passed incorrectly in request |
| 92 | +- Workspace disabled or suspended |
| 93 | +- Environment mismatch (dev key in production) |
| 94 | + |
| 95 | +**Events API issues:** |
| 96 | +- Batch structure malformed |
| 97 | +- Event validation failed (data plan) |
| 98 | +- Consent state blocking events |
| 99 | +- Kit filtering rules blocking |
| 100 | + |
| 101 | +**Identity API issues:** |
| 102 | +- Identity request validation failed |
| 103 | +- MPID not found (new user) |
| 104 | +- Identity callback error → silent failure |
| 105 | +- User identities malformed |
| 106 | + |
| 107 | +**Config API issues:** |
| 108 | +- Config fetch failed → kits not initialized |
| 109 | +- Config cache stale → using old settings |
| 110 | +- Server-side config override → unexpected behavior |
| 111 | + |
| 112 | +**Batch upload issues:** |
| 113 | +- Timer not advancing → events never sent |
| 114 | +- Batch size threshold not met → waiting for 100 events |
| 115 | +- Upload interval not met → waiting for 30 seconds |
| 116 | +- Network offline → queued but not sent |
| 117 | + |
| 118 | +## Obscure Debugging Vectors |
| 119 | + |
| 120 | +- **Network throttling**: Fast 3G reveals timeout issues |
| 121 | +- **Disable cache**: Force fresh requests to test caching theory |
| 122 | +- **Copy as fetch**: Right-click network request → replay in console |
| 123 | +- **fetch-mock logging**: Enable fetch-mock logging in tests |
| 124 | +- **Batch queue inspection**: Log `mpInstance._Batch` to see queued events |
| 125 | +- **Identity MPID check**: Verify MPID exists in localStorage |
| 126 | +- **Config inspection**: Check `mpInstance._Store` for loaded config |
| 127 | +- **Session ID check**: Verify session ID in event payload |
| 128 | + |
| 129 | +## Debugging Flow |
| 130 | + |
| 131 | +1. Reproduce failure, open network tab |
| 132 | +2. Identify request: sent? failed? wrong response? |
| 133 | +3. Check API key (devToken) in request |
| 134 | +4. Verify endpoint URL format (workspace ID, path) |
| 135 | +5. Compare fetch-mock handler vs real API response |
| 136 | +6. Log API client state before/after request |
| 137 | +7. Check batch queue status (if Events API) |
| 138 | +8. Test with network throttling enabled |
| 139 | + |
| 140 | +## Success Criteria |
| 141 | +- Request succeeds with correct response |
| 142 | +- Events uploaded to mParticle servers |
| 143 | +- Identity callbacks fire correctly |
| 144 | +- Config loaded and applied |
| 145 | +- Works across 3+ attempts (no fluke) |
| 146 | +- Screenshot: network tab + successful response |
| 147 | + |
| 148 | +## SDK-Specific API Patterns |
| 149 | + |
| 150 | +**Events API (`/v1/[workspace]/events`):** |
| 151 | +- Batch of events in payload |
| 152 | +- Response indicates success/failure per event |
| 153 | +- Retry logic for failed uploads |
| 154 | +- Validate event structure before sending |
| 155 | + |
| 156 | +**Identity API (`/v1/[workspace]/identify`):** |
| 157 | +- Single identity request |
| 158 | +- Callback with result (success/error) |
| 159 | +- MPID returned in response |
| 160 | +- User identities in request |
| 161 | + |
| 162 | +**Config API (`/v1/[workspace]/config`):** |
| 163 | +- Fetched on SDK init |
| 164 | +- Contains kit configurations |
| 165 | +- Workspace settings |
| 166 | +- Feature flags |
| 167 | + |
| 168 | +**Common Headers:** |
| 169 | +``` |
| 170 | +Content-Type: application/json |
| 171 | +User-Agent: mParticle web SDK |
| 172 | +``` |
| 173 | + |
| 174 | +## Test Debugging |
| 175 | + |
| 176 | +**fetch-mock configuration:** |
| 177 | +```typescript |
| 178 | +import fetchMock from 'fetch-mock/esm/client' |
| 179 | + |
| 180 | +fetchMock.post('/v1/test-workspace/events', { |
| 181 | + status: 200, |
| 182 | + body: { Store: true } |
| 183 | +}) |
| 184 | +``` |
| 185 | + |
| 186 | +**Verify mock called:** |
| 187 | +```typescript |
| 188 | +expect(fetchMock.called('/v1/test-workspace/events')).toBe(true) |
| 189 | +``` |
| 190 | + |
| 191 | +**Check request payload:** |
| 192 | +```typescript |
| 193 | +const calls = fetchMock.calls('/v1/test-workspace/events') |
| 194 | +console.log(JSON.parse(calls[0][1].body)) |
| 195 | +``` |
| 196 | + |
| 197 | +## Self-Improvement |
| 198 | +**CRITICAL**: Update with: |
| 199 | +- Events API contract changes |
| 200 | +- Identity API error patterns |
| 201 | +- Config API structure updates |
| 202 | +- Batch upload timing solutions |
| 203 | +- fetch-mock anti-patterns |
| 204 | +- Common SDK API failures |
0 commit comments