waba-toolkit 0.3.0 → 0.4.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,622 @@
1
+ # Troubleshooting Guide
2
+
3
+ Common issues and solutions.
4
+
5
+ ---
6
+
7
+ ## Installation Issues
8
+
9
+ > **New to the CLI?** Start with the [CLI Guide](CLI.md)
10
+
11
+ ### Command Not Found After Global Install
12
+
13
+ **Problem:**
14
+ ```bash
15
+ waba-toolkit: command not found
16
+ ```
17
+
18
+ **Solutions:**
19
+
20
+ 1. **Check npm global path:**
21
+ ```bash
22
+ npm config get prefix
23
+ # Should show: /usr/local or ~/.npm-global
24
+ ```
25
+
26
+ 2. **Add to PATH:**
27
+ ```bash
28
+ export PATH="$(npm config get prefix)/bin:$PATH"
29
+ ```
30
+
31
+ 3. **Use npx instead:**
32
+ ```bash
33
+ npx waba-toolkit <command>
34
+ ```
35
+
36
+ 4. **Reinstall:**
37
+ ```bash
38
+ npm uninstall -g waba-toolkit
39
+ npm install -g waba-toolkit
40
+ ```
41
+
42
+ ---
43
+
44
+ ## Configuration Issues
45
+
46
+ > **See also:** [CLI Configuration Guide](CLI.md#configuration-commands)
47
+
48
+ ### Config Decryption Failed
49
+
50
+ **Problem:**
51
+ ```
52
+ Failed to decrypt configuration
53
+ ```
54
+
55
+ **Causes:**
56
+ - Config moved to different machine
57
+ - Hostname changed
58
+ - MAC address changed
59
+
60
+ **Solution:**
61
+ ```bash
62
+ # Reconfigure (old config is backed up automatically)
63
+ waba-toolkit configure
64
+ ```
65
+
66
+ ### Missing Access Token
67
+
68
+ **Problem:**
69
+ ```
70
+ ✗ Error: Access token not found
71
+ ```
72
+
73
+ **Solutions:**
74
+
75
+ **Option 1: Configure**
76
+ ```bash
77
+ waba-toolkit configure
78
+ ```
79
+
80
+ **Option 2: Environment variable**
81
+ ```bash
82
+ export WABA_TOOLKIT_ACCESS_TOKEN="your-token"
83
+ ```
84
+
85
+ **Option 3: Update config**
86
+ ```bash
87
+ waba-toolkit config set access-token "your-token"
88
+ ```
89
+
90
+ ### Missing Phone Number ID
91
+
92
+ **Problem:**
93
+ ```
94
+ ✗ Error: No phone number ID specified
95
+ ```
96
+
97
+ **Solutions:**
98
+
99
+ **Option 1: Set default**
100
+ ```bash
101
+ waba-toolkit config set-default-phone 1234567890
102
+ ```
103
+
104
+ **Option 2: Environment variable**
105
+ ```bash
106
+ export WABA_TOOLKIT_PHONE_NUMBER_ID=1234567890
107
+ ```
108
+
109
+ **Option 3: Use flag**
110
+ ```bash
111
+ waba-toolkit send text --bpid 1234567890 --to 123 --message "Hi"
112
+ ```
113
+
114
+ ---
115
+
116
+ ## Webhook Issues
117
+
118
+ ### Signature Verification Fails
119
+
120
+ **Problem:**
121
+ ```typescript
122
+ const isValid = client.verifyWebhook(...);
123
+ // Returns false
124
+ ```
125
+
126
+ **Common causes:**
127
+
128
+ 1. **Using parsed JSON instead of raw body**
129
+ ```typescript
130
+ // ❌ Wrong
131
+ client.verifyWebhook(signature, JSON.stringify(req.body))
132
+
133
+ // ✅ Correct
134
+ client.verifyWebhook(signature, req.rawBody)
135
+ ```
136
+
137
+ 2. **Missing app secret**
138
+ ```typescript
139
+ // ❌ Wrong
140
+ const client = new WABAClient({
141
+ accessToken: '...',
142
+ });
143
+
144
+ // ✅ Correct
145
+ const client = new WABAClient({
146
+ accessToken: '...',
147
+ appSecret: process.env.META_APP_SECRET, // Required!
148
+ });
149
+ ```
150
+
151
+ 3. **Body was modified**
152
+ ```typescript
153
+ // Make sure to capture raw body BEFORE parsing:
154
+ app.use(express.json({
155
+ verify: (req, res, buf) => {
156
+ req.rawBody = buf.toString('utf8');
157
+ }
158
+ }));
159
+ ```
160
+
161
+ ### Webhook Timeouts
162
+
163
+ **Problem:** Webhooks timing out (20 second limit)
164
+
165
+ **Solution:** Respond immediately, process asynchronously
166
+
167
+ ```typescript
168
+ app.post('/webhook', async (req, res) => {
169
+ // Verify and respond immediately
170
+ if (!client.verifyWebhook(...)) {
171
+ return res.status(401).send('Invalid');
172
+ }
173
+
174
+ res.sendStatus(200); // Respond ASAP
175
+
176
+ // Process asynchronously
177
+ processWebhookAsync(req.body).catch(console.error);
178
+ });
179
+
180
+ async function processWebhookAsync(payload) {
181
+ // Heavy processing here...
182
+ }
183
+ ```
184
+
185
+ ---
186
+
187
+ ## Media Download Issues
188
+
189
+ ### Media Not Found (404)
190
+
191
+ **Problem:**
192
+ ```typescript
193
+ WABAMediaError: Media not found (404)
194
+ ```
195
+
196
+ **Causes:**
197
+ - Media ID is incorrect
198
+ - Media expired (typically 30 days)
199
+ - Temporary URL expired
200
+
201
+ **Solutions:**
202
+
203
+ 1. **Verify media ID:**
204
+ ```typescript
205
+ const mediaId = extractMediaId(message);
206
+ console.log('Media ID:', mediaId); // Check format
207
+ ```
208
+
209
+ 2. **Download promptly:**
210
+ Media expires after 30 days. Download soon after receiving webhook.
211
+
212
+ 3. **Retry logic:**
213
+ ```typescript
214
+ import pRetry from 'p-retry';
215
+
216
+ const media = await pRetry(
217
+ () => client.getMedia(mediaId),
218
+ { retries: 3 }
219
+ );
220
+ ```
221
+
222
+ ### Access Denied (403)
223
+
224
+ **Problem:**
225
+ ```typescript
226
+ WABAMediaError: Access denied (403)
227
+ ```
228
+
229
+ **Solutions:**
230
+
231
+ 1. **Check token permissions:**
232
+ - Token needs `whatsapp_business_messaging` permission
233
+ - Generate new token if needed
234
+
235
+ 2. **Verify WABA ownership:**
236
+ - Media must belong to your WhatsApp Business Account
237
+
238
+ ### Memory Issues
239
+
240
+ **Problem:** Out of memory when downloading large files
241
+
242
+ **Solution:** Use streams, not buffers
243
+
244
+ ```typescript
245
+ // ❌ High memory (loads entire file)
246
+ const { buffer } = await client.getMedia(mediaId, { asBuffer: true });
247
+
248
+ // ✅ Low memory (streams)
249
+ const { stream } = await client.getMedia(mediaId);
250
+ Readable.fromWeb(stream).pipe(fs.createWriteStream('./file'));
251
+ ```
252
+
253
+ ---
254
+
255
+ ## Message Sending Issues
256
+
257
+ ### Re-engagement Required (131047)
258
+
259
+ **Problem:**
260
+ ```json
261
+ {
262
+ "error": {
263
+ "code": 131047,
264
+ "message": "Re-engagement message"
265
+ }
266
+ }
267
+ ```
268
+
269
+ **Cause:** More than 24 hours since customer's last message
270
+
271
+ **Solution:** Use approved template message
272
+
273
+ ```typescript
274
+ // Check last message time
275
+ const hoursSince = (Date.now() - lastMessageTime) / 1000 / 60 / 60;
276
+
277
+ if (hoursSince > 24) {
278
+ // Use template
279
+ await client.sendTemplateMessage(to, {
280
+ name: 'approved_template',
281
+ language: { code: 'en' },
282
+ });
283
+ } else {
284
+ // Use regular text
285
+ await client.sendTextMessage(to, 'Hello');
286
+ }
287
+ ```
288
+
289
+ ### Invalid Phone Number (100)
290
+
291
+ **Problem:**
292
+ ```json
293
+ {
294
+ "error": {
295
+ "code": 100,
296
+ "message": "Invalid parameter"
297
+ }
298
+ }
299
+ ```
300
+
301
+ **Solutions:**
302
+
303
+ 1. **Check format:** Use E.164 format (no + or spaces)
304
+ ```typescript
305
+ // ❌ Wrong
306
+ '+ 1 555 0100'
307
+ '+1-555-0100'
308
+
309
+ // ✅ Correct
310
+ '15550100'
311
+ ```
312
+
313
+ 2. **Verify on WhatsApp:**
314
+ Number must have WhatsApp installed
315
+
316
+ ### Rate Limited (368)
317
+
318
+ **Problem:**
319
+ ```json
320
+ {
321
+ "error": {
322
+ "code": 368,
323
+ "message": "Temporarily blocked"
324
+ }
325
+ }
326
+ ```
327
+
328
+ **Solutions:**
329
+
330
+ 1. **Reduce send rate:**
331
+ ```typescript
332
+ import pLimit from 'p-limit';
333
+
334
+ const limit = pLimit(10); // Max 10 concurrent
335
+
336
+ await Promise.all(
337
+ recipients.map(to => limit(() => client.sendTextMessage(to, text)))
338
+ );
339
+ ```
340
+
341
+ 2. **Implement exponential backoff:**
342
+ ```typescript
343
+ import pRetry from 'p-retry';
344
+
345
+ await pRetry(
346
+ () => client.sendTextMessage(to, text),
347
+ {
348
+ retries: 5,
349
+ factor: 2,
350
+ minTimeout: 1000,
351
+ }
352
+ );
353
+ ```
354
+
355
+ ### Token Expired (190)
356
+
357
+ **Problem:**
358
+ ```json
359
+ {
360
+ "error": {
361
+ "code": 190,
362
+ "message": "Access token expired"
363
+ }
364
+ }
365
+ ```
366
+
367
+ **Solution:** Generate new access token
368
+
369
+ 1. Go to **Meta Business Suite** → **Settings**
370
+ 2. Create new System User token
371
+ 3. Update config:
372
+ ```bash
373
+ waba-toolkit config set access-token "new-token"
374
+ ```
375
+
376
+ ---
377
+
378
+ ## Type Errors
379
+
380
+ ### Type Mismatch in Classified Message
381
+
382
+ **Problem:**
383
+ ```typescript
384
+ const classified = classifyMessage(message);
385
+ // TypeScript error: Property 'text' does not exist
386
+ console.log(classified.message.text.body);
387
+ ```
388
+
389
+ **Solution:** Use type narrowing
390
+
391
+ ```typescript
392
+ const classified = classifyMessage(message);
393
+
394
+ if (classified.type === 'text') {
395
+ // TypeScript now knows: classified.message is TextMessage
396
+ console.log(classified.message.text.body);
397
+ }
398
+ ```
399
+
400
+ ---
401
+
402
+ ## Network Issues
403
+
404
+ ### Connection Timeout
405
+
406
+ **Problem:**
407
+ ```
408
+ WABANetworkError: Request timeout
409
+ ```
410
+
411
+ **Solutions:**
412
+
413
+ 1. **Check internet connection**
414
+
415
+ 2. **Verify Meta API status:**
416
+ https://developers.facebook.com/status/
417
+
418
+ 3. **Retry with exponential backoff:**
419
+ ```typescript
420
+ import pRetry from 'p-retry';
421
+
422
+ await pRetry(
423
+ () => client.sendTextMessage(to, text),
424
+ {
425
+ retries: 3,
426
+ onFailedAttempt: error => {
427
+ console.log(`Retry ${error.attemptNumber}`);
428
+ }
429
+ }
430
+ );
431
+ ```
432
+
433
+ ---
434
+
435
+ ## CLI Specific Issues
436
+
437
+ ### Permission Denied
438
+
439
+ **Problem:**
440
+ ```bash
441
+ EACCES: permission denied
442
+ ```
443
+
444
+ **Solutions:**
445
+
446
+ **Option 1: Use npx**
447
+ ```bash
448
+ npx waba-toolkit <command>
449
+ ```
450
+
451
+ **Option 2: Fix npm permissions**
452
+ ```bash
453
+ mkdir ~/.npm-global
454
+ npm config set prefix '~/.npm-global'
455
+ export PATH=~/.npm-global/bin:$PATH
456
+ npm install -g waba-toolkit
457
+ ```
458
+
459
+ **Option 3: Use sudo** (not recommended)
460
+ ```bash
461
+ sudo npm install -g waba-toolkit
462
+ ```
463
+
464
+ ### JSON File Not Found
465
+
466
+ **Problem:**
467
+ ```bash
468
+ waba-toolkit send template --file template.json
469
+ # Error: ENOENT: no such file
470
+ ```
471
+
472
+ **Solutions:**
473
+
474
+ 1. **Check file path:**
475
+ ```bash
476
+ ls -la template.json
477
+ pwd
478
+ ```
479
+
480
+ 2. **Use absolute path:**
481
+ ```bash
482
+ waba-toolkit send template --file /full/path/to/template.json
483
+ ```
484
+
485
+ 3. **Check current directory:**
486
+ ```bash
487
+ waba-toolkit send template --file ./template.json
488
+ ```
489
+
490
+ ---
491
+
492
+ ## Testing Issues
493
+
494
+ ### Test Webhooks Not Arriving
495
+
496
+ **Checklist:**
497
+
498
+ 1. **Verify webhook URL is public:**
499
+ ```bash
500
+ curl https://your-domain.com/webhook
501
+ ```
502
+
503
+ 2. **Check webhook verification:**
504
+ ```typescript
505
+ // GET /webhook handler required
506
+ app.get('/webhook', (req, res) => {
507
+ const mode = req.query['hub.mode'];
508
+ const token = req.query['hub.verify_token'];
509
+ const challenge = req.query['hub.challenge'];
510
+
511
+ if (mode === 'subscribe' && token === process.env.VERIFY_TOKEN) {
512
+ res.status(200).send(challenge);
513
+ } else {
514
+ res.sendStatus(403);
515
+ }
516
+ });
517
+ ```
518
+
519
+ 3. **Check webhook subscriptions:**
520
+ - Go to **Meta App Dashboard** → **WhatsApp** → **Configuration**
521
+ - Verify webhook fields are subscribed (messages, message_status)
522
+
523
+ 4. **Check logs:**
524
+ - Meta provides webhook delivery logs in App Dashboard
525
+
526
+ ---
527
+
528
+ ## Getting Help
529
+
530
+ ### Include This Information
531
+
532
+ When opening an issue:
533
+
534
+ 1. **Version:**
535
+ ```bash
536
+ npm list waba-toolkit
537
+ ```
538
+
539
+ 2. **Error message:**
540
+ ```bash
541
+ # Full error output
542
+ ```
543
+
544
+ 3. **Code snippet:**
545
+ ```typescript
546
+ // Minimal reproducible example
547
+ ```
548
+
549
+ 4. **fbtrace_id:** (if Meta API error)
550
+ ```json
551
+ {
552
+ "error": {
553
+ "fbtrace_id": "ABC123..." // Include this
554
+ }
555
+ }
556
+ ```
557
+
558
+ ### Resources
559
+
560
+ - **GitHub Issues:** https://github.com/teknicus/waba-toolkit/issues
561
+ - **Meta API Docs:** https://developers.facebook.com/docs/whatsapp
562
+ - **Meta Support:** https://business.facebook.com/business/help
563
+ - **Meta API Status:** https://developers.facebook.com/status/
564
+
565
+ ---
566
+
567
+ ## Quick Diagnostic
568
+
569
+ Run this script to check your setup:
570
+
571
+ ```typescript
572
+ import { WABAClient, WABAApiClient } from 'waba-toolkit';
573
+
574
+ async function diagnostic() {
575
+ console.log('=== waba-toolkit Diagnostic ===\n');
576
+
577
+ // Check environment variables
578
+ console.log('1. Environment Variables:');
579
+ console.log(' ACCESS_TOKEN:', process.env.META_ACCESS_TOKEN ? '✓' : '✗');
580
+ console.log(' APP_SECRET:', process.env.META_APP_SECRET ? '✓' : '✗');
581
+ console.log(' PHONE_ID:', process.env.PHONE_NUMBER_ID ? '✓' : '✗');
582
+
583
+ // Test media client
584
+ console.log('\n2. WABAClient:');
585
+ try {
586
+ const client = new WABAClient({
587
+ accessToken: process.env.META_ACCESS_TOKEN,
588
+ });
589
+ console.log(' Initialized: ✓');
590
+ } catch (error) {
591
+ console.log(' Initialized: ✗', error.message);
592
+ }
593
+
594
+ // Test API client
595
+ console.log('\n3. WABAApiClient:');
596
+ try {
597
+ const apiClient = new WABAApiClient({
598
+ accessToken: process.env.META_ACCESS_TOKEN,
599
+ phoneNumberId: process.env.PHONE_NUMBER_ID,
600
+ });
601
+ console.log(' Initialized: ✓');
602
+
603
+ // Test API call
604
+ const phones = await apiClient.listPhoneNumbers(process.env.WABA_ID);
605
+ console.log(' API call: ✓ (' + phones.data.length + ' phones)');
606
+ } catch (error) {
607
+ console.log(' API call: ✗', error.message);
608
+ }
609
+
610
+ console.log('\n=== End Diagnostic ===');
611
+ }
612
+
613
+ diagnostic();
614
+ ```
615
+
616
+ ---
617
+
618
+ ## Next Steps
619
+
620
+ - [CLI Guide](CLI.md) - CLI usage
621
+ - [API Reference](../API_REFERENCE.md) - Complete API documentation
622
+ - [GitHub Issues](https://github.com/teknicus/waba-toolkit/issues) - Report bugs