| 1 |
# Troubleshooting — Balanced Breakfast |
| 2 |
|
| 3 |
## Plugin Fetch Failures |
| 4 |
|
| 5 |
**Symptoms:** Feed shows yellow (degraded) or red (circuit broken) status. |
| 6 |
|
| 7 |
### Error Categories |
| 8 |
|
| 9 |
|
| 10 |
|
| 11 |
| **Transient** | DNS timeout, HTTP 500/502/503 | Yes | After 10 failures | |
| 12 |
| **RateLimited** | HTTP 429 | Yes (after delay) | Never | |
| 13 |
| **Auth** | HTTP 401/403, invalid API key | No | Immediate | |
| 14 |
| **Config** | HTTP 404/410, bad URL, missing field | No | Immediate | |
| 15 |
| **Parse** | Malformed RSS/JSON/XML | Yes | After 10 failures | |
| 16 |
|
| 17 |
### Decision Tree |
| 18 |
|
| 19 |
1. **Feed shows red (circuit broken)?** |
| 20 |
- Check `last_error` in feed details for the error category |
| 21 |
- **Auth error** → Fix API key/credentials in feed config, then "Reset & Retry" |
| 22 |
- **Config error** → Verify feed URL exists and is accessible, delete and re-add |
| 23 |
- **10+ transient failures** → Wait for service recovery, then "Reset & Retry" |
| 24 |
|
| 25 |
2. **Feed shows yellow (degraded)?** |
| 26 |
- System retries automatically |
| 27 |
- If persistent: verify URL, check API key, try manual retry |
| 28 |
|
| 29 |
3. **Feed never updates?** |
| 30 |
- Plugin `.rhai` file missing from `plugins/` → restart app |
| 31 |
- Auto-fetch disabled → check settings |
| 32 |
- Circuit breaker tripped → see above |
| 33 |
|
| 34 |
## Circuit Breaker |
| 35 |
|
| 36 |
- **Threshold:** 10 consecutive failures for transient/parse errors. Auth/config errors trip immediately. |
| 37 |
- **Rate-limited errors** do NOT increment the failure counter. |
| 38 |
- **Reset:** Feed menu → "Reset & Retry" (calls `reset_circuit_breaker_and_fetch`) |
| 39 |
- **What reset does:** Sets `circuit_broken=false`, `consecutive_failures=0`, clears `last_error`, attempts fresh fetch |
| 40 |
|
| 41 |
## OPML Import Issues |
| 42 |
|
| 43 |
|
| 44 |
|
| 45 |
| "Invalid OPML: ..." | Malformed XML | Validate OPML syntax (must be valid XML with `<outline>` elements) | |
| 46 |
| URLs skipped | Non-http/https URLs in OPML | Edit OPML to use only http/https URLs | |
| 47 |
| Feeds already exist | Duplicate URLs | Expected — `skipped` counter shows how many were duplicates | |
| 48 |
| Import result shows errors | Database or URL validation failures | Check error messages in import result, fix individual URLs | |
| 49 |
|
| 50 |
**Import result format:** `{ imported: N, skipped: N, errors: [...] }` |
| 51 |
|
| 52 |
## Secret Decryption Failures |
| 53 |
|
| 54 |
**Symptoms:** Feeds with API keys show auth errors despite correct credentials. |
| 55 |
|
| 56 |
**Encryption scheme:** AES-256-GCM, format `bb_enc:v1:<base64(nonce || ciphertext || tag)>` |
| 57 |
|
| 58 |
|
| 59 |
|
| 60 |
| Feed auth errors after OS reinstall | Encryption key lost from keychain | Delete feeds, re-add with credentials (auto-encrypts on save) | |
| 61 |
| "Decryption failed" in logs | Wrong key or corrupted ciphertext | Delete `~/.config/balanced-breakfast/encryption.key`, restart (generates new key). Re-add feeds. | |
| 62 |
| Keychain unavailable | macOS Keychain locked, Linux Secret Service not running | Unlock keychain or start D-Bus Secret Service | |
| 63 |
|
| 64 |
**Key storage priority:** |
| 65 |
1. OS keychain (macOS Keychain, Windows Credential Manager, Linux Secret Service) |
| 66 |
2. Fallback: `~/.config/balanced-breakfast/encryption.key` (file, 0600 permissions) |
| 67 |
|
| 68 |
**Backward compatibility:** Unencrypted secret values pass through on decrypt and get encrypted on next config change. |
| 69 |
|
| 70 |
## Plugin Sandbox Violations |
| 71 |
|
| 72 |
|
| 73 |
|
| 74 |
| "Script execution exceeded operation limit" | 100,000 operations per fetch | Plugin has infinite loop or very inefficient logic | |
| 75 |
| "Max recursion level exceeded" | 32 call levels | Refactor plugin to iterative approach | |
| 76 |
| "HTTP request limit exceeded" | 100 requests per fetch | Plugin making too many HTTP calls | |
| 77 |
| "Fetch timeout exceeded" | 60s aggregate per fetch | Plugin spending too long overall | |
| 78 |
| "Blocked request to internal address" | localhost/private IPs blocked | Plugin trying SSRF — use public URLs only | |
| 79 |
|
| 80 |
**Per-request timeout:** 15 seconds. **Response size limit:** 2 MB. |
| 81 |
|
| 82 |
## Database Issues |
| 83 |
|
| 84 |
**Database location:** `~/.local/share/balanced-breakfast/` (platform-dependent), SQLite via sqlx. |
| 85 |
|
| 86 |
|
| 87 |
|
| 88 |
| App won't start, migration error | Delete DB file, restart (fresh DB, re-sync from cloud) | |
| 89 |
| "database is locked" | Close other app instances, exclude DB from antivirus | |
| 90 |
| FTS5 search returns no results | Rebuild FTS index: delete `feed_items_fts` table, restart app | |
| 91 |
|
| 92 |
## Sync Issues |
| 93 |
|
| 94 |
Same SyncKit integration as GoingsOn: |
| 95 |
- Credentials stored in OS keychain |
| 96 |
- Push/pull with changelog triggers |
| 97 |
- `applying_remote` flag can get stuck — restart app to clear |
| 98 |
- Sync interval: 15 minutes (configurable) |
| 99 |
|
| 100 |
**What syncs:** Feed subscriptions, feed tags, user config, query feeds, item read/star state. Item content does NOT sync (fetched independently per device). |
| 101 |
|
| 102 |
## Error Codes |
| 103 |
|
| 104 |
|
| 105 |
|
| 106 |
| `BAD_REQUEST` | Invalid input (bad OPML, missing field) | |
| 107 |
| `NOT_FOUND` | Feed or resource doesn't exist | |
| 108 |
| `DATABASE` | SQLite error | |
| 109 |
| `INTERNAL` | Unexpected error | |
| 110 |
| `PLUGIN` | Rhai plugin error (sandbox violation, runtime error) | |
| 111 |
|