@buivietphi/skill-mobile-mt 2.0.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,787 @@
1
+ # Debugging Intelligence — Deep Pattern Database
2
+
3
+ > On-demand. Load when: complex bugs, long stack traces, issue investigation, multi-error scenarios.
4
+ > This file contains 30+ real error patterns with EXACT search strategies.
5
+
6
+ ---
7
+
8
+ ## Platform Focus Rule
9
+
10
+ ```
11
+ ⛔ ONLY use error patterns for the DETECTED platform. Don't scan all categories.
12
+
13
+ REACT NATIVE → Category A (RN crashes) + B + C + D + E + F1
14
+ FLUTTER → Category A2 (Flutter crashes) + B4 + C + D + F3
15
+ iOS NATIVE → Category A3 (iOS crashes) + C + D + F1
16
+ ANDROID → Category A4 (Android crashes) + B3 + C + D + F2
17
+
18
+ Cross-platform categories (B build, C network, D state, E navigation):
19
+ → Use the platform-specific SEARCH strategy within each category
20
+ → e.g., C1 Network error: RN → check axios/fetch, Flutter → check http/dio,
21
+ iOS → check URLSession, Android → check Retrofit/OkHttp
22
+
23
+ CROSS-REFERENCE native ONLY WHEN:
24
+ → Stack trace exits JS/Dart layer into native (Java/Swift/ObjC)
25
+ → Error message is from native runtime (not Metro/Dart VM)
26
+ → User explicitly says the bug is in native code
27
+ ```
28
+
29
+ ---
30
+
31
+ ## Error Pattern Database
32
+
33
+ ### Category A: React Native Runtime Crashes
34
+
35
+ #### A1. "undefined is not an object (evaluating 'X.Y')"
36
+ ```
37
+ CAUSE: X is null/undefined when accessing property Y
38
+ SEARCH: Grep "X" in src/ → find where X is defined/assigned → check null cases
39
+ COMMON:
40
+ - API response missing field → data?.field instead of data.field
41
+ - Navigation params undefined → route.params?.id
42
+ - State not initialized → useState(null) accessed before set
43
+ - Unmounted component accessing state
44
+ FIX: Add optional chaining (X?.Y) OR null guard (if (!X) return)
45
+ VERIFY: Check ALL places X is used (grep) → apply same fix
46
+ ```
47
+
48
+ #### A2. "Cannot read property 'X' of undefined" / "Cannot read properties of null"
49
+ ```
50
+ CAUSE: Same as A1 (V8/Hermes variant)
51
+ SEARCH: Same strategy — Grep the variable name in src/
52
+ NOTE: In Hermes, the variable name may not be in error → check stack trace for file:line
53
+ ```
54
+
55
+ #### A3. "TypeError: X is not a function"
56
+ ```
57
+ CAUSE: X is imported wrong, or the object doesn't have method X
58
+ SEARCH: Grep "X" in src/ → check the import statement → check the module's exports
59
+ COMMON:
60
+ - Default vs named import mismatch: import X vs import { X }
61
+ - Calling method on wrong object: obj.X() but X is on obj.child
62
+ - Library updated with breaking API change
63
+ - Circular import making X undefined at call time
64
+ FIX: Fix import OR check object shape with console.log(typeof X)
65
+ ```
66
+
67
+ #### A4. "Invariant Violation: Element type is invalid"
68
+ ```
69
+ CAUSE: React component imported incorrectly (got undefined instead of component)
70
+ SEARCH: Find the component import → check its source file's export
71
+ COMMON:
72
+ - export default vs export { Component } mismatch
73
+ - File path typo in import
74
+ - Circular import (A imports B imports A → one becomes undefined)
75
+ - Re-exporting from index.ts but forgot to add new component
76
+ FIX: Fix export/import → clear Metro cache → restart
77
+ ```
78
+
79
+ #### A5. "Maximum call stack size exceeded"
80
+ ```
81
+ CAUSE: Infinite loop or infinite recursion
82
+ SEARCH: Find the function from stack trace → check for:
83
+ - useEffect with wrong dependency array (causes infinite re-render)
84
+ - State update inside render body (not in handler/effect)
85
+ - Recursive function without base case
86
+ - Component renders itself without stop condition
87
+ COMMON:
88
+ - useEffect(() => { setState(x) }, [x]) ← x changes → effect runs → sets x → loop
89
+ - componentDidUpdate without shouldComponentUpdate check
90
+ FIX: Fix dependency array OR add base case OR memoize
91
+ ```
92
+
93
+ #### A6. "VirtualizedList: You have a large list that is slow to update"
94
+ ```
95
+ CAUSE: FlatList re-rendering entire list on every state change
96
+ SEARCH: Find the FlatList component → check renderItem + keyExtractor
97
+ COMMON:
98
+ - Missing keyExtractor (uses index by default → full re-render)
99
+ - renderItem creates new function/object every render
100
+ - Data source reference changes on every render
101
+ FIX:
102
+ → Add keyExtractor with stable unique ID
103
+ → Wrap renderItem in useCallback
104
+ → Memoize list item component with React.memo
105
+ → Use getItemLayout if fixed height
106
+ ```
107
+
108
+ #### A7. "Unhandled promise rejection"
109
+ ```
110
+ CAUSE: Async function threw error without try/catch
111
+ SEARCH: Find the async function from stack trace → check error handling
112
+ COMMON:
113
+ - fetch/axios call without try/catch
114
+ - Promise chain without .catch()
115
+ - async function in useEffect without error handler
116
+ FIX: Wrap in try/catch → show user-facing error → log for debugging
117
+ ```
118
+
119
+ ---
120
+
121
+ ### Category A2: Flutter Runtime Crashes
122
+
123
+ #### A2-1. "setState() called after dispose()"
124
+ ```
125
+ CAUSE: Async callback completes after widget unmounted, calls setState
126
+ SEARCH: Find the widget from stack trace → check async callbacks
127
+ COMMON:
128
+ - Future.then() callback without mounted check
129
+ - Timer callback after screen popped
130
+ - Stream listener not cancelled in dispose()
131
+ FIX: Add `if (!mounted) return;` before EVERY setState after async gap
132
+ VERIFY: Check ALL async callbacks in the widget → add mounted guard
133
+ ```
134
+
135
+ #### A2-2. "RenderFlex overflowed by X pixels"
136
+ ```
137
+ CAUSE: Child widget exceeds parent constraint
138
+ SEARCH: Find the widget from error → check its parent Row/Column layout
139
+ COMMON:
140
+ - Text too long in Row without Flexible/Expanded
141
+ - Image with fixed size in constrained container
142
+ - Column inside Column without Expanded
143
+ FIX: Wrap with Flexible/Expanded OR add overflow: TextOverflow.ellipsis
144
+ OR wrap with SingleChildScrollView
145
+ ```
146
+
147
+ #### A2-3. "A build function returned null"
148
+ ```
149
+ CAUSE: Switch/if in build() doesn't cover all cases → returns null
150
+ SEARCH: Find the widget's build method → check conditional branches
151
+ COMMON:
152
+ - Enum switch without default case
153
+ - if/else if without final else
154
+ - Late variable not initialized before build
155
+ FIX: Ensure ALL branches return a Widget, add default/else case
156
+ ```
157
+
158
+ #### A2-4. "Looking up a deactivated widget's ancestor is unsafe"
159
+ ```
160
+ CAUSE: Using BuildContext after async gap (context may be deactivated)
161
+ SEARCH: Find the async function → check context usage after await
162
+ COMMON:
163
+ - Navigator.of(context).pop() after await
164
+ - ScaffoldMessenger.of(context) after async call
165
+ - showDialog after await
166
+ FIX: Store navigator/messenger BEFORE await, OR check mounted after await
167
+ VERIFY: Check ALL context usage after await in the widget
168
+ ```
169
+
170
+ #### A2-5. "type 'Null' is not a subtype of type 'X'"
171
+ ```
172
+ CAUSE: Null value assigned to non-nullable variable (sound null safety violation)
173
+ SEARCH: Find the variable from stack trace → trace where null comes from
174
+ COMMON:
175
+ - JSON parsing: map['key'] as String (but key is absent → null)
176
+ - API response missing expected field
177
+ - Type cast: (object as String) when object is null
178
+ FIX: Use null-safe parsing: map['key'] as String? ?? 'default'
179
+ OR fix fromJson factory to handle missing fields
180
+ ```
181
+
182
+ #### A2-6. "Unhandled Exception: Bad state: Stream has already been listened to"
183
+ ```
184
+ CAUSE: Single-subscription Stream listened to more than once
185
+ SEARCH: Find the StreamController → check how many widgets listen to it
186
+ COMMON:
187
+ - StreamController (default = single-subscription) used by multiple widgets
188
+ - Hot reload re-subscribes without cancelling previous
189
+ FIX: Use StreamController.broadcast() for multiple listeners
190
+ OR ensure single listener with StreamSubscription tracking
191
+ ```
192
+
193
+ ---
194
+
195
+ ### Category A3: iOS Swift Runtime Crashes
196
+
197
+ #### A3-1. "Fatal error: Unexpectedly found nil while unwrapping an Optional value"
198
+ ```
199
+ CAUSE: Force unwrap (!) on nil value
200
+ SEARCH: Find file:line from crash log → check the ! operator
201
+ COMMON:
202
+ - IBOutlet not connected in storyboard
203
+ - UserDefaults.string(forKey:)! for missing key
204
+ - as! cast that fails
205
+ - Implicitly unwrapped optional (!) on property not set before access
206
+ FIX: Replace ! with guard let / if let / ?? default
207
+ VERIFY: Grep "!" in the file → check ALL force unwraps
208
+ ```
209
+
210
+ #### A3-2. "EXC_BAD_ACCESS (code=1/2)" / SIGSEGV
211
+ ```
212
+ CAUSE: Accessing deallocated memory (dangling pointer / use-after-free)
213
+ SEARCH: Enable Zombie Objects in Xcode → reproduce → find deallocated object
214
+ COMMON:
215
+ - Strong reference to self in closure → VC deallocated but closure keeps pointer
216
+ - Accessing unowned self after object deallocated
217
+ - Core Data object accessed from wrong thread
218
+ - C/ObjC interop with wrong pointer management
219
+ FIX: Use [weak self] instead of [unowned self] if lifetime uncertain
220
+ Use perform() for Core Data thread safety
221
+ ```
222
+
223
+ #### A3-3. "Thread 1: signal SIGABRT" / "NSInternalInconsistencyException"
224
+ ```
225
+ CAUSE: Assertion failure in UIKit/Foundation
226
+ SEARCH: Read "reason:" line in crash log → search for that assertion
227
+ COMMON:
228
+ - UITableView: batch update mismatch (insert/delete count != data count)
229
+ - Storyboard: IBOutlet or segue identifier not found
230
+ - Auto Layout: conflicting constraints
231
+ - Collection view: invalid number of items in section
232
+ FIX: Fix data source consistency → diffable data source recommended
233
+ Fix storyboard connections → check identifier spelling
234
+ ```
235
+
236
+ #### A3-4. "Modifications to the layout engine must not be performed from a background thread"
237
+ ```
238
+ CAUSE: UI update called from background thread
239
+ SEARCH: Find the code from stack trace → check which queue it runs on
240
+ COMMON:
241
+ - URLSession completion handler (runs on background by default)
242
+ - NotificationCenter observer callback
243
+ - DispatchQueue.global() { self.label.text = "..." }
244
+ FIX: Wrap UI updates: DispatchQueue.main.async { ... }
245
+ OR use @MainActor on the function
246
+ OR use MainActor.run { ... } in async context
247
+ ```
248
+
249
+ #### A3-5. "Cannot decode" / "DecodingError.keyNotFound"
250
+ ```
251
+ CAUSE: JSON response doesn't match Codable struct
252
+ SEARCH: Find the Codable struct → compare with actual API response
253
+ COMMON:
254
+ - Backend added new required field → old Codable struct missing it
255
+ - Backend returns null for field marked as non-optional
256
+ - Backend changed field type (string → number)
257
+ - Snake_case vs camelCase mismatch without CodingKeys
258
+ FIX: Mark uncertain fields as Optional → provide CodingKeys if naming differs
259
+ Use custom init(from:) with try? for graceful degradation
260
+ ```
261
+
262
+ ---
263
+
264
+ ### Category A4: Android Kotlin Runtime Crashes
265
+
266
+ #### A4-1. "java.lang.NullPointerException" / "KotlinNullPointerException"
267
+ ```
268
+ CAUSE: Null access — !! force unwrap, Java interop, or platform type
269
+ SEARCH: Find file:line from stack trace → check the null source
270
+ COMMON:
271
+ - intent.extras!!.getString("key") → extras is null from deep link
272
+ - findViewById<TextView>(R.id.title)!! → wrong layout inflated
273
+ - Java library returning null where Kotlin expects non-null (platform types)
274
+ - binding.textView after onDestroyView (binding is null)
275
+ FIX: Replace !! with ?. ?: default OR requireNotNull with message
276
+ Use _binding pattern for Fragment view binding
277
+ ```
278
+
279
+ #### A4-2. "java.lang.IllegalStateException: Fragment not attached to an activity"
280
+ ```
281
+ CAUSE: Fragment operation after detach (network callback, delayed handler)
282
+ SEARCH: Find the Fragment from stack trace → check lifecycle state
283
+ COMMON:
284
+ - requireContext() in coroutine that outlives Fragment
285
+ - requireActivity() in async callback
286
+ - getString(R.string.x) after detach
287
+ FIX: Use context (nullable) instead of requireContext()
288
+ Check isAdded before Fragment operations
289
+ Use viewLifecycleOwner.lifecycleScope for coroutines
290
+ ```
291
+
292
+ #### A4-3. "android.os.TransactionTooLargeException"
293
+ ```
294
+ CAUSE: Bundle/Intent data > 500KB (Binder transaction limit ~1MB shared)
295
+ SEARCH: Find what data is passed via Intent/Bundle → check size
296
+ COMMON:
297
+ - Passing large Parcelable object between Activities
298
+ - SavedInstanceState accumulating data over config changes
299
+ - Fragment arguments with large list
300
+ FIX: Pass ID only → load data in destination from DB/API
301
+ Use ViewModel for data sharing between Fragments
302
+ Clear savedInstanceState in onSaveInstanceState if too large
303
+ ```
304
+
305
+ #### A4-4. "java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState"
306
+ ```
307
+ CAUSE: Fragment transaction after onSaveInstanceState (state loss)
308
+ SEARCH: Find the Fragment transaction → check when it's called
309
+ COMMON:
310
+ - commitNow() in async callback that fires after onPause
311
+ - show()/hide() dialog after Activity paused
312
+ - Navigation action after onStop
313
+ FIX: Use commitAllowingStateLoss() (last resort)
314
+ Better: check lifecycle state before transaction
315
+ Best: use Navigation component (handles this automatically)
316
+ ```
317
+
318
+ #### A4-5. "android.view.WindowManager$BadTokenException"
319
+ ```
320
+ CAUSE: Showing dialog/toast with invalid Activity context
321
+ SEARCH: Find the dialog/toast creation → check Activity lifecycle
322
+ COMMON:
323
+ - Show AlertDialog after Activity finished
324
+ - Toast with Activity context after destroy
325
+ - PopupWindow with destroyed Activity reference
326
+ FIX: Check !isFinishing && !isDestroyed before showing dialog
327
+ Use applicationContext for Toast (not Activity context)
328
+ ```
329
+
330
+ #### A4-6. "java.util.ConcurrentModificationException"
331
+ ```
332
+ CAUSE: Modifying collection while iterating over it
333
+ SEARCH: Find the collection from stack trace → check for/forEach loops
334
+ COMMON:
335
+ - for (item in list) { list.remove(item) }
336
+ - LiveData/Flow emitting new list while observer iterates old
337
+ - Multiple coroutines modifying same MutableList
338
+ FIX: Use toList() copy for iteration → modify original
339
+ Use CopyOnWriteArrayList for concurrent access
340
+ Use Mutex for coroutine synchronization
341
+ ```
342
+
343
+ ---
344
+
345
+ ### Category B: Build Errors
346
+
347
+ #### B1. "Module not found: Can't resolve 'X'"
348
+ ```
349
+ ⚠️ SEARCH ORDER IS DIFFERENT FOR BUILD ERRORS:
350
+ 1. package.json → is X installed? → npm install X
351
+ 2. tsconfig.json → paths alias configured? → check paths mapping
352
+ 3. src/ imports → typo in import path? → fix path
353
+ 4. node_modules/ → X exists but wrong version? → update
354
+ DO NOT search src/ first — this is a dependency/config issue
355
+ ```
356
+
357
+ #### B2. "Type 'X' is not assignable to type 'Y'"
358
+ ```
359
+ CAUSE: TypeScript type mismatch
360
+ SEARCH:
361
+ 1. Find type/interface Y definition → Grep "interface Y" or "type Y" in src/
362
+ 2. Find where X is created → check what shape it actually has
363
+ 3. Compare actual vs expected → find the mismatch
364
+ COMMON:
365
+ - API response shape changed but types not updated
366
+ - Optional field treated as required (add ?)
367
+ - Union type not narrowed (add type guard)
368
+ FIX: Fix the type to match reality OR fix the data to match the type
369
+ ```
370
+
371
+ #### B3. "Duplicate class found in modules"
372
+ ```
373
+ SEARCH: android/app/build.gradle → dependency tree
374
+ → ./gradlew app:dependencies | grep "[class-name]"
375
+ DO NOT search src/ — this is purely a Gradle dependency issue
376
+ ```
377
+
378
+ #### B4. "Pod install failed" / "CocoaPods could not find compatible versions"
379
+ ```
380
+ SEARCH: ios/Podfile → check version constraints
381
+ → pod outdated → find conflicting pods
382
+ → Podfile.lock → check locked versions
383
+ DO NOT search src/ — this is iOS dependency management
384
+ FIX: pod deintegrate → rm Podfile.lock → pod install --repo-update
385
+ ```
386
+
387
+ ---
388
+
389
+ ### Category C: Network / API Errors
390
+
391
+ #### C1. "Network request failed" / HTTP 0
392
+ ```
393
+ SEARCH:
394
+ 1. Find API base URL → Grep "baseURL" or "BASE_URL" in src/
395
+ 2. Find .env file → check API URL value
396
+ 3. Find the failing endpoint → Grep the endpoint path in src/
397
+ 4. Check interceptors → Grep "interceptor" in src/
398
+ COMMON:
399
+ - Wrong BASE_URL in .env (localhost on device → use IP)
400
+ - SSL certificate issue (dev server with self-signed cert)
401
+ - Missing internet permission (Android: AndroidManifest.xml)
402
+ - Request interceptor throwing error before request is sent
403
+ ```
404
+
405
+ #### C2. HTTP 401 Unauthorized
406
+ ```
407
+ SEARCH:
408
+ 1. Find auth token storage → Grep "token" or "accessToken" in src/
409
+ 2. Find auth interceptor → Grep "Authorization" in src/
410
+ 3. Find token refresh logic → Grep "refresh" in src/
411
+ COMMON:
412
+ - Token expired but refresh not implemented
413
+ - Token stored but not attached to request headers
414
+ - Token refresh race condition (multiple 401 → multiple refresh calls)
415
+ FIX: Check token exists → check it's attached → check expiry → add refresh
416
+ ```
417
+
418
+ #### C3. HTTP 403 Forbidden
419
+ ```
420
+ SEARCH: Find the API call → check headers + auth token + user role
421
+ COMMON:
422
+ - Token valid but user lacks permission (role/scope issue)
423
+ - CSRF token missing (web views)
424
+ - API key vs OAuth token confusion
425
+ ```
426
+
427
+ #### C4. HTTP 500 Internal Server Error
428
+ ```
429
+ SEARCH: Find the API call → check request payload shape
430
+ COMMON:
431
+ - Sending wrong data shape (missing required field)
432
+ - Backend bug (not your mobile code) → check backend logs
433
+ - Payload too large (file upload without compression)
434
+ NOTE: If backend is also your project → search backend src/ for the endpoint handler
435
+ ```
436
+
437
+ ---
438
+
439
+ ### Category D: State / Data Errors
440
+
441
+ #### D1. "Screen shows old/stale data"
442
+ ```
443
+ SEARCH:
444
+ 1. Find the data-fetching function → Grep "fetch" or "query" or "useQuery" in screens/
445
+ 2. Find the cache/state management → Grep "store" or "cache" in src/
446
+ 3. Check refetch triggers → when does data refresh?
447
+ COMMON:
448
+ - Cache not invalidated after mutation
449
+ - Navigation doesn't trigger re-fetch (useFocusEffect missing)
450
+ - Optimistic update didn't sync with server
451
+ FIX: Add refetch on focus OR invalidate cache after mutation OR add pull-to-refresh
452
+ ```
453
+
454
+ #### D2. "State updates not reflecting in UI"
455
+ ```
456
+ SEARCH: Find the component → check state management
457
+ COMMON:
458
+ - Mutating state directly: state.items.push(x) instead of setState([...state.items, x])
459
+ - Object reference not changing: setState(sameObj) → React skips re-render
460
+ - Zustand/Redux selector not selecting the changed field
461
+ - Async state update batching issue
462
+ FIX: Always create NEW references for state updates
463
+ ```
464
+
465
+ #### D3. "Race condition — UI flickers / wrong data appears briefly"
466
+ ```
467
+ SEARCH: Find the component → check useEffect deps + async calls
468
+ COMMON:
469
+ - Two async calls racing, slower one overwrites faster result
470
+ - State update from previous screen applied to current screen
471
+ - Optimistic update visible before server confirms
472
+ FIX: AbortController for fetch → cancel previous request on new one
473
+ OR use unique request ID → ignore stale responses
474
+ ```
475
+
476
+ ---
477
+
478
+ ### Category E: Navigation Errors
479
+
480
+ #### E1. "Screen not found / Route not registered"
481
+ ```
482
+ SEARCH:
483
+ 1. Grep the screen name in src/navigation/ or src/router/
484
+ 2. Check ALL navigator files → is the screen registered?
485
+ 3. Grep "navigate(" or "push(" in src/ → find where it's called
486
+ COMMON:
487
+ - Screen name typo: "ProductDetail" vs "ProductDetails"
488
+ - Screen defined in wrong navigator (nested navigators)
489
+ - Screen conditionally rendered (auth gate) but user not authenticated
490
+ ```
491
+
492
+ #### E2. "Navigation params undefined"
493
+ ```
494
+ SEARCH: Find the navigate call → check what params are passed → find the target screen → check what it expects
495
+ COMMON:
496
+ - Forgot to pass params: navigate('Screen') instead of navigate('Screen', { id })
497
+ - Param name mismatch: { itemId } vs route.params.id
498
+ - Deep link opens screen without params → add default/fallback
499
+ ```
500
+
501
+ ---
502
+
503
+ ### Category F: Platform-Specific Errors
504
+
505
+ #### F1. iOS: "App crashes only on real device (works on simulator)"
506
+ ```
507
+ SEARCH:
508
+ 1. Check Xcode console logs on real device (connect + run)
509
+ 2. Grep for simulator-only code: __DEV__, Platform.OS checks
510
+ COMMON:
511
+ - Missing privacy permission (camera, location, photos → Info.plist)
512
+ - Keychain access restricted on device (not available in simulator mode)
513
+ - ARM vs x86 architecture issue
514
+ - Code signing / provisioning profile issue
515
+ ```
516
+
517
+ #### F2. Android: "App crashes only on older devices (works on new)"
518
+ ```
519
+ SEARCH:
520
+ 1. Check minSdkVersion in android/app/build.gradle
521
+ 2. Grep for API-level-specific code → missing compatibility check
522
+ COMMON:
523
+ - Using API not available on older Android (WebView, Notification channels)
524
+ - Missing desugaring for Java 8+ features
525
+ - Memory limit lower on older devices → OOM on large images
526
+ ```
527
+
528
+ #### F3. Flutter: "RenderFlex overflowed by X pixels"
529
+ ```
530
+ SEARCH: Find the widget from error → check its parent layout constraints
531
+ COMMON:
532
+ - Text too long in Row without Flexible/Expanded
533
+ - Image with fixed size in constrained container
534
+ - Column with unbounded children in ScrollView
535
+ FIX: Wrap in Flexible/Expanded OR add overflow: TextOverflow.ellipsis OR use SingleChildScrollView
536
+ ```
537
+
538
+ ---
539
+
540
+ ## Issue Investigation Workflow
541
+
542
+ ```
543
+ When user says "check this issue" / "investigate" / "look into":
544
+
545
+ STEP 1: READ the issue fully
546
+ → Don't skim — read every word
547
+ → Identify: what feature? what's expected? what's actual?
548
+
549
+ STEP 2: EXTRACT search terms
550
+ → Feature name (e.g., "checkout", "profile", "notification")
551
+ → Component/screen name (e.g., "CartScreen", "PaymentForm")
552
+ → Error message (if any)
553
+ → User action that triggers it (e.g., "tap submit", "pull to refresh")
554
+
555
+ STEP 3: SEARCH project
556
+ → Grep feature name in src/
557
+ → Glob for screen/component files
558
+ → Read the relevant code (3-5 files max)
559
+
560
+ STEP 4: TRACE the flow
561
+ → User action → event handler → state change → API call → response → UI update
562
+ → Find where the flow breaks
563
+
564
+ STEP 5: REPORT (don't fix yet)
565
+ → "I found [component] at [file:line]."
566
+ → "Current behavior: [what code does]."
567
+ → "The issue is likely: [root cause based on code read]."
568
+ → "Confidence: [high/medium/low] based on [evidence]."
569
+ → "Want me to fix it?"
570
+
571
+ STEP 6: FIX (only if user says yes)
572
+ → Propose specific change with before/after
573
+ → Check side effects
574
+ → Verify types match
575
+ ```
576
+
577
+ ---
578
+
579
+ ## Git-Aware Debugging (Check Recent Changes First)
580
+
581
+ ```
582
+ ⛔ BEFORE deep-diving into code, CHECK WHAT CHANGED RECENTLY.
583
+ ⛔ 80%+ of bugs are caused by RECENT CHANGES — find them first.
584
+
585
+ PRE-CHECK: IS THIS A GIT PROJECT?
586
+ → Run: git rev-parse --is-inside-work-tree 2>/dev/null
587
+ → If command fails / returns false → NOT a git project → SKIP this section
588
+ → If git repo but no commits (git log fails) → SKIP this section
589
+ → If git repo with commits → proceed below
590
+
591
+ STEP 1: CHECK GIT HISTORY
592
+ → git log --oneline -10 → recent commits
593
+ → git diff HEAD~3 --name-only → files changed recently
594
+ → git diff HEAD~3 -- [broken_file_path] → exact changes to broken file
595
+ → git log --oneline --all -- [broken_file_path] → full file history
596
+
597
+ STEP 2: ANALYZE RECENT CHANGES
598
+ → Did any recent commit touch the broken file/feature?
599
+ → If YES → read the diff → the bug is likely IN that diff
600
+ → If NO → bug is environmental/data-driven → proceed to Root Cause below
601
+
602
+ STEP 3: GIT BISECT (for "it used to work" bugs)
603
+ → If user says "it worked before" / "it broke recently":
604
+ → Find last known-good commit: git log --oneline -20
605
+ → Compare: git diff [good_commit]..HEAD -- [affected_files]
606
+ → The bug is in that diff
607
+
608
+ STEP 4: DEPENDENCY CHANGES
609
+ → git diff HEAD~5 -- package.json pubspec.yaml build.gradle Podfile
610
+ → Did any dependency version change? → common source of breakage
611
+ → Check: lock file changes (yarn.lock, pubspec.lock, Podfile.lock)
612
+
613
+ SKIP GIT-AWARE DEBUGGING WHEN:
614
+ → Project has NO git initialized (no .git/ folder)
615
+ → git init done but zero commits yet
616
+ → Brand new project (no meaningful history)
617
+ → User explicitly says "this never worked" (not a regression)
618
+ → Build error from fresh install (dependency/config issue)
619
+ ```
620
+
621
+ ---
622
+
623
+ ## Root Cause Analysis Framework (5-Step Tracing)
624
+
625
+ ```
626
+ ⛔ NO FIXES WITHOUT ROOT CAUSE INVESTIGATION FIRST
627
+ ⛔ NO COMPLETION CLAIMS WITHOUT FRESH VERIFICATION EVIDENCE
628
+
629
+ STEP 1: OBSERVE — What exactly happens?
630
+ → What user action triggers it? (tap, scroll, navigate, submit)
631
+ → What is the EXACT error/behavior? (not paraphrased — exact)
632
+ → When does it happen? (always / sometimes / after [action] / on [platform])
633
+ → Classify reproduction:
634
+ ALWAYS → deterministic — trace step by step
635
+ SOMETIMES → race condition / timing — check async flow
636
+ ONLY on [device] → platform/hardware — check native layer
637
+ ONLY after [X] → state-dependent — trace state mutations
638
+ FIRST TIME ONLY → initialization — check setup/config
639
+
640
+ STEP 2: IMMEDIATE CAUSE — What code throws?
641
+ → Find the EXACT file:line from error/stack trace
642
+ → Read that file → what is the code doing at that line?
643
+ → What variable/value is wrong? What should it be?
644
+ → This is the IMMEDIATE cause (not root cause yet)
645
+
646
+ STEP 3: TRACE BACKWARD — What called this?
647
+ → WHO calls this function? (Grep for callers in src/)
648
+ → What data does the caller pass? Trace the data origin
649
+ → Go one level up: who calls the CALLER?
650
+ → Keep going until you find where the bad data ENTERED
651
+
652
+ STEP 4: FIND THE ROOT — Where does the chain break?
653
+ → The root cause is where CORRECT data becomes INCORRECT
654
+ → It's NOT the crash line — it's where the corruption starts
655
+ → Common root causes:
656
+ - API response missing field (backend changed, frontend didn't)
657
+ - State not reset between screens (stale data leaks)
658
+ - Race condition: async A and B, B finishes first overwrites A
659
+ - Missing null check at data boundary (API → app)
660
+ - Wrong assumption about data shape (type says X, reality is Y)
661
+ → VERIFY: does this root cause explain ALL symptoms?
662
+ - If yes → proceed to fix
663
+ - If no → your theory is wrong → go back to Step 3
664
+
665
+ STEP 5: FIX + DEFENSE IN DEPTH
666
+ → Fix the root cause (not just the crash line)
667
+ → Then add validation at EVERY layer data passes through:
668
+ Layer 1: API response validation (did backend send what we expect?)
669
+ Layer 2: State mutation guard (is the data valid before storing?)
670
+ Layer 3: Component prop check (does the component handle null/empty?)
671
+ Layer 4: Render guard (does UI degrade gracefully?)
672
+ → Goal: make the bug STRUCTURALLY IMPOSSIBLE to recur
673
+ → Not just "fix this one case" — prevent the entire CLASS of bug
674
+ → Cite: "Root cause: [file:line] — [explanation]"
675
+ → Cite: "Defense: added validation at [layers]"
676
+ ```
677
+
678
+ ---
679
+
680
+ ## Single Hypothesis Protocol
681
+
682
+ ```
683
+ ⛔ NEVER stack multiple fixes at once
684
+ ⛔ NEVER "fix it and also refactor nearby code"
685
+
686
+ PROTOCOL:
687
+ 1. Form ONE hypothesis from root cause analysis
688
+ 2. Make the SMALLEST possible change to test it
689
+ 3. Verify: does it fix the bug?
690
+ → YES → proceed to defense-in-depth
691
+ → NO → REVERT the change → form NEW hypothesis
692
+ 4. Never carry forward a failed fix
693
+ 5. If 3 hypotheses fail → STOP and question architecture:
694
+ → "I've tried 3 approaches and none fixed it.
695
+ This suggests the issue is architectural, not a simple bug.
696
+ Options: (1) [rethink approach], (2) [alternative pattern], (3) [ask user]"
697
+
698
+ WHY THIS MATTERS:
699
+ - Stacking fixes hides which one actually worked
700
+ - Multiple changes create new bugs while "fixing" old ones
701
+ - Clean revert = clean slate for next hypothesis
702
+ ```
703
+
704
+ ---
705
+
706
+ ## Red Flags — Anti-Rationalization Table
707
+
708
+ ```
709
+ 🚩 If you catch yourself saying/thinking these, STOP immediately:
710
+
711
+ WHAT YOU SAY WHAT IT MEANS WHAT TO DO
712
+ ─────────────────────────────────────────────────────────────────────────
713
+ "Should work now" You didn't verify RUN IT. Read output.
714
+ "I'm confident this fixes it" Confidence ≠ evidence Show the evidence.
715
+ "I think the issue is..." You haven't traced the code Trace it. Cite file:line.
716
+ "Let me also clean up..." Scope creep during bug fix STOP. Fix bug only.
717
+ "Probably a race condition" Buzzword without proof PROVE with async trace.
718
+ "Try changing X to Y" You haven't read the file Read it FIRST.
719
+ "This is a known issue with X" You're pattern-matching Verify in THIS project.
720
+ Stacking 3+ changes at once You're guessing Revert. 1 change only.
721
+ Same fix attempted 3+ times Architecture problem STOP. Question approach.
722
+ "Works on my end" Didn't test other platform Test both. Or say untested.
723
+ ```
724
+
725
+ ---
726
+
727
+ ## Multi-Error Triage
728
+
729
+ ```
730
+ When user has MULTIPLE errors (common during upgrades/migrations):
731
+
732
+ 1. SORT by dependency:
733
+ → Which error causes other errors? Fix that one FIRST
734
+ → Build errors before runtime errors
735
+ → Import errors before type errors
736
+ → Config errors before code errors
737
+
738
+ 2. FIND THE ROOT:
739
+ → 5 errors might all come from 1 root cause
740
+ → Example: wrong package version → type errors + build errors + runtime errors
741
+ → Fix the version → all 5 errors disappear
742
+
743
+ 3. FIX IN ORDER:
744
+ → Root cause first
745
+ → Then verify: did other errors disappear?
746
+ → If yes → done
747
+ → If no → fix remaining one by one
748
+
749
+ 4. NEVER fix all errors at once without understanding relationships
750
+ ```
751
+
752
+ ---
753
+
754
+ ## Debugging Commands Cheat Sheet
755
+
756
+ ```
757
+ REACT NATIVE:
758
+ Clear all caches: npx react-native start --reset-cache
759
+ Rebuild iOS: cd ios && rm -rf build && pod install && cd ..
760
+ Rebuild Android: cd android && ./gradlew clean && cd ..
761
+ Full nuke: rm -rf node_modules ios/Pods ios/build android/build && yarn && cd ios && pod install
762
+ Check linking: npx react-native config
763
+ Check bundle: npx react-native bundle --entry-file index.js --platform ios --dev false
764
+
765
+ FLUTTER:
766
+ Clear all: flutter clean && flutter pub get
767
+ Analyze: flutter analyze
768
+ Check deps: flutter pub outdated
769
+ Full rebuild: flutter clean && flutter pub get && cd ios && pod install && cd ..
770
+
771
+ EXPO:
772
+ Clear cache: npx expo start --clear
773
+ Check config: npx expo config
774
+ Prebuild: npx expo prebuild --clean
775
+ Doctor: npx expo-doctor
776
+
777
+ iOS:
778
+ Clean build: xcodebuild clean -workspace ios/App.xcworkspace -scheme App
779
+ Device logs: idevicesyslog (via libimobiledevice)
780
+ Simulator logs: xcrun simctl spawn booted log stream --level error
781
+
782
+ ANDROID:
783
+ Logcat filter: adb logcat *:E | grep "com.yourapp"
784
+ Clear app data: adb shell pm clear com.yourapp
785
+ Check crash: adb logcat -b crash
786
+ Screenshot: adb exec-out screencap -p > /tmp/screen.png
787
+ ```