@buivietphi/skill-mobile-mt 1.0.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.
- package/AGENTS.md +392 -0
- package/README.md +224 -0
- package/SKILL.md +1048 -0
- package/android/android-native.md +208 -0
- package/bin/install.mjs +199 -0
- package/flutter/flutter.md +246 -0
- package/ios/ios-native.md +182 -0
- package/package.json +50 -0
- package/react-native/react-native.md +743 -0
- package/shared/agent-rules-template.md +343 -0
- package/shared/anti-patterns.md +407 -0
- package/shared/bug-detection.md +71 -0
- package/shared/claude-md-template.md +125 -0
- package/shared/code-review.md +121 -0
- package/shared/common-pitfalls.md +117 -0
- package/shared/document-analysis.md +167 -0
- package/shared/error-recovery.md +467 -0
- package/shared/observability.md +688 -0
- package/shared/performance-prediction.md +210 -0
- package/shared/platform-excellence.md +159 -0
- package/shared/prompt-engineering.md +677 -0
- package/shared/release-checklist.md +82 -0
- package/shared/version-management.md +509 -0
|
@@ -0,0 +1,467 @@
|
|
|
1
|
+
# Error Recovery — Fix Common Build/Runtime Errors
|
|
2
|
+
|
|
3
|
+
> Quick reference for fixing errors AI agents encounter during mobile development.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Build Errors
|
|
8
|
+
|
|
9
|
+
### 1. Duplicate class found
|
|
10
|
+
|
|
11
|
+
**Symptom:**
|
|
12
|
+
```
|
|
13
|
+
Duplicate class X found in modules Y and Z
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
**Cause:** Multiple versions of the same library in dependency tree
|
|
17
|
+
|
|
18
|
+
**Fix:**
|
|
19
|
+
```bash
|
|
20
|
+
# Find conflict
|
|
21
|
+
./gradlew app:dependencies | grep "library-name"
|
|
22
|
+
|
|
23
|
+
# Force version in android/app/build.gradle
|
|
24
|
+
android {
|
|
25
|
+
configurations.all {
|
|
26
|
+
resolutionStrategy {
|
|
27
|
+
force 'com.library:name:1.2.3'
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
### 2. Metro bundler failed: Module not found
|
|
36
|
+
|
|
37
|
+
**Symptom:**
|
|
38
|
+
```
|
|
39
|
+
Error: Unable to resolve module X from Y
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
**Cause:** Import path wrong OR package not installed OR cache stale
|
|
43
|
+
|
|
44
|
+
**Fix:**
|
|
45
|
+
```bash
|
|
46
|
+
# 1. Check import path is correct
|
|
47
|
+
# 2. Install missing package
|
|
48
|
+
yarn add package-name
|
|
49
|
+
|
|
50
|
+
# 3. Clear cache and restart
|
|
51
|
+
rm -rf node_modules
|
|
52
|
+
yarn install
|
|
53
|
+
yarn start --reset-cache
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
### 3. Pod install failed
|
|
59
|
+
|
|
60
|
+
**Symptom:**
|
|
61
|
+
```
|
|
62
|
+
[!] CDN: trunk URL couldn't be downloaded
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
**Cause:** CocoaPods CDN slow/blocked OR network issue
|
|
66
|
+
|
|
67
|
+
**Fix:**
|
|
68
|
+
```bash
|
|
69
|
+
# Option 1: Use GitHub source
|
|
70
|
+
cd ios
|
|
71
|
+
rm Podfile.lock
|
|
72
|
+
pod cache clean --all
|
|
73
|
+
pod install --repo-update
|
|
74
|
+
|
|
75
|
+
# Option 2: Add to Podfile (top)
|
|
76
|
+
source 'https://github.com/CocoaPods/Specs.git'
|
|
77
|
+
|
|
78
|
+
# Option 3: Deintegrate and reinstall
|
|
79
|
+
pod deintegrate
|
|
80
|
+
pod install
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
### 4. Gradle sync failed: Could not resolve
|
|
86
|
+
|
|
87
|
+
**Symptom:**
|
|
88
|
+
```
|
|
89
|
+
Could not resolve com.library:name:1.2.3
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
**Cause:** Maven repo unreachable OR wrong credentials OR version doesn't exist
|
|
93
|
+
|
|
94
|
+
**Fix:**
|
|
95
|
+
```gradle
|
|
96
|
+
// android/build.gradle — add backup repos
|
|
97
|
+
allprojects {
|
|
98
|
+
repositories {
|
|
99
|
+
google()
|
|
100
|
+
mavenCentral()
|
|
101
|
+
maven { url 'https://jitpack.io' } // Backup
|
|
102
|
+
maven { url 'https://maven.google.com' } // Backup
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
### 5. Xcode build failed: Command PhaseScriptExecution failed
|
|
110
|
+
|
|
111
|
+
**Symptom:**
|
|
112
|
+
```
|
|
113
|
+
Command PhaseScriptExecution failed with a nonzero exit code
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
**Cause:** Build script error OR missing file OR wrong Xcode version
|
|
117
|
+
|
|
118
|
+
**Fix:**
|
|
119
|
+
```bash
|
|
120
|
+
# 1. Clean build folder
|
|
121
|
+
cd ios
|
|
122
|
+
rm -rf build
|
|
123
|
+
xcodebuild clean
|
|
124
|
+
|
|
125
|
+
# 2. Reinstall pods
|
|
126
|
+
rm -rf Pods Podfile.lock
|
|
127
|
+
pod install
|
|
128
|
+
|
|
129
|
+
# 3. Check Xcode version matches project requirement
|
|
130
|
+
xcodebuild -version
|
|
131
|
+
|
|
132
|
+
# 4. Check script in Xcode → Build Phases → Run Script
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
### 6. Android build failed: Invoke-customs are only supported starting with Android O
|
|
138
|
+
|
|
139
|
+
**Symptom:**
|
|
140
|
+
```
|
|
141
|
+
Invoke-customs are only supported starting with Android O (--min-api 26)
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
**Cause:** Using Java 8+ features but minSdkVersion < 26
|
|
145
|
+
|
|
146
|
+
**Fix:**
|
|
147
|
+
```gradle
|
|
148
|
+
// android/app/build.gradle
|
|
149
|
+
android {
|
|
150
|
+
defaultConfig {
|
|
151
|
+
minSdkVersion 21 // Keep if targeting older devices
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
compileOptions {
|
|
155
|
+
sourceCompatibility JavaVersion.VERSION_1_8
|
|
156
|
+
targetCompatibility JavaVersion.VERSION_1_8
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// Enable desugaring for older Android versions
|
|
160
|
+
compileOptions {
|
|
161
|
+
coreLibraryDesugaringEnabled true
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
dependencies {
|
|
166
|
+
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
|
|
167
|
+
}
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## Runtime Errors
|
|
173
|
+
|
|
174
|
+
### 7. App crashes on launch (no error message)
|
|
175
|
+
|
|
176
|
+
**Debug steps:**
|
|
177
|
+
```bash
|
|
178
|
+
# iOS: Check Xcode console
|
|
179
|
+
# Android: Check Logcat
|
|
180
|
+
adb logcat | grep -i "crash\|exception\|error"
|
|
181
|
+
|
|
182
|
+
# Common causes:
|
|
183
|
+
✅ Missing native module (forgot pod install / gradle sync)
|
|
184
|
+
✅ Broken import (typo in file path)
|
|
185
|
+
✅ Missing entry point (index.js not registered)
|
|
186
|
+
✅ Version mismatch (RN CLI vs RN runtime)
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
**Fix:**
|
|
190
|
+
1. Check native logs first (always)
|
|
191
|
+
2. Verify `pod install` and `./gradlew clean` were run
|
|
192
|
+
3. Check `AppRegistry.registerComponent` matches app name
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
### 8. White screen / blank screen
|
|
197
|
+
|
|
198
|
+
**Symptom:** App launches but shows blank white screen
|
|
199
|
+
|
|
200
|
+
**Cause:** Error caught by error boundary OR navigator not setup OR Metro bundler not running
|
|
201
|
+
|
|
202
|
+
**Debug:**
|
|
203
|
+
```bash
|
|
204
|
+
# 1. Check Metro is running
|
|
205
|
+
yarn start
|
|
206
|
+
|
|
207
|
+
# 2. Check console for errors (cmd+D / cmd+M → Debug)
|
|
208
|
+
|
|
209
|
+
# 3. Add error boundary
|
|
210
|
+
class ErrorBoundary extends React.Component {
|
|
211
|
+
componentDidCatch(error, errorInfo) {
|
|
212
|
+
console.log('Caught error:', error, errorInfo);
|
|
213
|
+
}
|
|
214
|
+
render() {
|
|
215
|
+
return this.props.children;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
**Fix:**
|
|
221
|
+
- Check navigator has screens registered
|
|
222
|
+
- Check no circular imports
|
|
223
|
+
- Check entry component is exported correctly
|
|
224
|
+
|
|
225
|
+
---
|
|
226
|
+
|
|
227
|
+
### 9. API requests not working
|
|
228
|
+
|
|
229
|
+
**Symptom:** Network calls fail silently OR return 0 / undefined
|
|
230
|
+
|
|
231
|
+
**Debug:**
|
|
232
|
+
```bash
|
|
233
|
+
# Check network logs
|
|
234
|
+
npx react-devtools
|
|
235
|
+
# OR
|
|
236
|
+
# Install Flipper + Network plugin
|
|
237
|
+
|
|
238
|
+
# Common causes:
|
|
239
|
+
✅ Interceptor blocking request (check auth token attached)
|
|
240
|
+
✅ CORS issue (web only, not mobile)
|
|
241
|
+
✅ SSL pinning blocking localhost (disable in dev)
|
|
242
|
+
✅ Wrong base URL (check environment variable)
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
**Fix:**
|
|
246
|
+
```typescript
|
|
247
|
+
// Check interceptor logs
|
|
248
|
+
api.interceptors.request.use((config) => {
|
|
249
|
+
console.log('Request:', config.url, config.headers);
|
|
250
|
+
return config;
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
api.interceptors.response.use(
|
|
254
|
+
(res) => {
|
|
255
|
+
console.log('Response:', res.status, res.data);
|
|
256
|
+
return res;
|
|
257
|
+
},
|
|
258
|
+
(error) => {
|
|
259
|
+
console.log('Error:', error.response?.status, error.message);
|
|
260
|
+
return Promise.reject(error);
|
|
261
|
+
}
|
|
262
|
+
);
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
---
|
|
266
|
+
|
|
267
|
+
### 10. Images not showing
|
|
268
|
+
|
|
269
|
+
**Symptom:** `<Image source={require('./image.png')} />` shows nothing
|
|
270
|
+
|
|
271
|
+
**Cause:** Wrong path OR image not in bundle OR cache issue
|
|
272
|
+
|
|
273
|
+
**Fix:**
|
|
274
|
+
```typescript
|
|
275
|
+
// ❌ Wrong
|
|
276
|
+
<Image source={require('../../assets/image.png')} />
|
|
277
|
+
|
|
278
|
+
// ✅ Correct — use absolute path with babel-plugin-module-resolver
|
|
279
|
+
<Image source={require('@assets/image.png')} />
|
|
280
|
+
|
|
281
|
+
// OR use static method to check
|
|
282
|
+
Image.resolveAssetSource(require('./image.png'))
|
|
283
|
+
.then(resolved => console.log(resolved))
|
|
284
|
+
|
|
285
|
+
// Clear cache
|
|
286
|
+
yarn start --reset-cache
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
---
|
|
290
|
+
|
|
291
|
+
### 11. Hermes crashes: Cannot read property 'X' of undefined
|
|
292
|
+
|
|
293
|
+
**Symptom:** Works on dev, crashes on release build with Hermes
|
|
294
|
+
|
|
295
|
+
**Cause:** Hermes strictness OR Proxy not supported OR polyfill missing
|
|
296
|
+
|
|
297
|
+
**Fix:**
|
|
298
|
+
```javascript
|
|
299
|
+
// Check Hermes is enabled
|
|
300
|
+
// android/app/build.gradle
|
|
301
|
+
project.ext.react = [
|
|
302
|
+
enableHermes: true // Make sure this is true
|
|
303
|
+
]
|
|
304
|
+
|
|
305
|
+
// Add polyfills for missing features
|
|
306
|
+
// index.js (top)
|
|
307
|
+
import 'react-native-get-random-values'; // For uuid
|
|
308
|
+
import 'react-native-url-polyfill/auto'; // For URL API
|
|
309
|
+
|
|
310
|
+
// Avoid Proxy (not supported)
|
|
311
|
+
❌ const proxy = new Proxy(obj, handler);
|
|
312
|
+
✅ Use plain objects instead
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
---
|
|
316
|
+
|
|
317
|
+
### 12. Navigation not working after upgrade
|
|
318
|
+
|
|
319
|
+
**Symptom:** Screen transitions broken OR `navigation.navigate` does nothing
|
|
320
|
+
|
|
321
|
+
**Cause:** Breaking changes in @react-navigation upgrade
|
|
322
|
+
|
|
323
|
+
**Fix:**
|
|
324
|
+
```typescript
|
|
325
|
+
// Check version compatibility
|
|
326
|
+
// React Navigation v6 requires:
|
|
327
|
+
"@react-navigation/native": "^6.x.x"
|
|
328
|
+
"react-native-screens": "^3.x.x"
|
|
329
|
+
"react-native-safe-area-context": "^4.x.x"
|
|
330
|
+
|
|
331
|
+
// Wrap root in NavigationContainer (only once)
|
|
332
|
+
<NavigationContainer>
|
|
333
|
+
<RootNavigator />
|
|
334
|
+
</NavigationContainer>
|
|
335
|
+
|
|
336
|
+
// Check screen names match exactly
|
|
337
|
+
navigation.navigate('ProductDetail', { id: 123 });
|
|
338
|
+
// vs
|
|
339
|
+
<Stack.Screen name="ProductDetail" component={...} />
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
---
|
|
343
|
+
|
|
344
|
+
### 13. Android release build works, debug doesn't (or vice versa)
|
|
345
|
+
|
|
346
|
+
**Symptom:** App works in one mode but not the other
|
|
347
|
+
|
|
348
|
+
**Cause:** ProGuard stripping code OR different signing configs OR debug-only dependencies
|
|
349
|
+
|
|
350
|
+
**Fix:**
|
|
351
|
+
```gradle
|
|
352
|
+
// android/app/proguard-rules.pro
|
|
353
|
+
-keep class com.yourpackage.** { *; }
|
|
354
|
+
-keep class * extends com.facebook.react.bridge.ReactContextBaseJavaModule { *; }
|
|
355
|
+
|
|
356
|
+
// Check signing configs
|
|
357
|
+
android {
|
|
358
|
+
buildTypes {
|
|
359
|
+
debug {
|
|
360
|
+
signingConfig signingConfigs.debug
|
|
361
|
+
}
|
|
362
|
+
release {
|
|
363
|
+
signingConfig signingConfigs.release
|
|
364
|
+
minifyEnabled true
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
---
|
|
371
|
+
|
|
372
|
+
## Flutter Specific
|
|
373
|
+
|
|
374
|
+
### 14. Flutter build failed: Gradle task assembleDebug failed with exit code 1
|
|
375
|
+
|
|
376
|
+
**Fix:**
|
|
377
|
+
```bash
|
|
378
|
+
# Clean and rebuild
|
|
379
|
+
flutter clean
|
|
380
|
+
flutter pub get
|
|
381
|
+
cd android && ./gradlew clean
|
|
382
|
+
cd .. && flutter build apk
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
### 15. Flutter: setState() called after dispose()
|
|
386
|
+
|
|
387
|
+
**Cause:** Async operation finished after widget unmounted
|
|
388
|
+
|
|
389
|
+
**Fix:**
|
|
390
|
+
```dart
|
|
391
|
+
// Add mounted check
|
|
392
|
+
if (!mounted) return;
|
|
393
|
+
setState(() { ... });
|
|
394
|
+
|
|
395
|
+
// OR cancel subscription in dispose
|
|
396
|
+
StreamSubscription? _sub;
|
|
397
|
+
|
|
398
|
+
@override
|
|
399
|
+
void dispose() {
|
|
400
|
+
_sub?.cancel();
|
|
401
|
+
super.dispose();
|
|
402
|
+
}
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
---
|
|
406
|
+
|
|
407
|
+
## iOS Specific
|
|
408
|
+
|
|
409
|
+
### 16. iOS: App rejected for missing privacy manifest
|
|
410
|
+
|
|
411
|
+
**Symptom:** App rejected during review — "Missing privacy manifest"
|
|
412
|
+
|
|
413
|
+
**Fix:**
|
|
414
|
+
```
|
|
415
|
+
Add PrivacyInfo.xcprivacy to Xcode project:
|
|
416
|
+
1. Right-click on project → New File → App Privacy File
|
|
417
|
+
2. Add required disclosures for tracking/data usage
|
|
418
|
+
3. Rebuild and resubmit
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
---
|
|
422
|
+
|
|
423
|
+
## Quick Reference
|
|
424
|
+
|
|
425
|
+
| Error | First Thing to Check |
|
|
426
|
+
|-------|---------------------|
|
|
427
|
+
| Build fails | Clean + reinstall deps (pod install / ./gradlew clean) |
|
|
428
|
+
| App crashes | Native logs (Xcode console / adb logcat) |
|
|
429
|
+
| White screen | Metro bundler running? Error boundary logs? |
|
|
430
|
+
| API fails | Network logs (Flipper / DevTools) + interceptor logs |
|
|
431
|
+
| Images missing | Correct path? Cache cleared? |
|
|
432
|
+
| Navigation broken | Screen names match? NavigationContainer wraps root? |
|
|
433
|
+
|
|
434
|
+
---
|
|
435
|
+
|
|
436
|
+
## General Recovery Protocol
|
|
437
|
+
|
|
438
|
+
```
|
|
439
|
+
1. READ ERROR MESSAGE FULLY
|
|
440
|
+
Don't skim — error message has the answer 80% of the time
|
|
441
|
+
|
|
442
|
+
2. CHECK RECENT CHANGES
|
|
443
|
+
What did you modify? Undo and test.
|
|
444
|
+
|
|
445
|
+
3. CLEAR CACHES
|
|
446
|
+
yarn start --reset-cache
|
|
447
|
+
rm -rf node_modules && yarn
|
|
448
|
+
cd ios && pod deintegrate && pod install
|
|
449
|
+
cd android && ./gradlew clean
|
|
450
|
+
|
|
451
|
+
4. CHECK NATIVE LOGS
|
|
452
|
+
iOS: Xcode console
|
|
453
|
+
Android: adb logcat
|
|
454
|
+
|
|
455
|
+
5. ISOLATE THE ISSUE
|
|
456
|
+
Comment out code until it works, then narrow down
|
|
457
|
+
|
|
458
|
+
6. GOOGLE THE EXACT ERROR
|
|
459
|
+
Copy full error message + framework name
|
|
460
|
+
|
|
461
|
+
7. ASK FOR HELP
|
|
462
|
+
Provide: error message + platform + version + what you tried
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
---
|
|
466
|
+
|
|
467
|
+
> When in doubt: clean everything, reinstall everything, restart everything.
|