# Bug Tracker
> Vibe Reader — Known issues, challenges, and their resolution status
> Last Updated: 2026-02-07
---
## Format
Each bug follows this structure:
- **ID:** Unique identifier (BUG-XXX)
- **Status:** `Open` | `In Progress` | `Resolved` | `Won't Fix`
- **Severity:** `Critical` | `High` | `Medium` | `Low`
- **Description:** What's happening
- **Steps to Reproduce:** How to trigger the issue
- **Root Cause:** Technical explanation (if known)
- **Resolution:** How it was fixed (if resolved)
---
## Open Issues
*No open issues at this time.*
---
## Resolved Issues
### BUG-R007: No Feedback on "Tap to Look Up" for Converted Words
**Status:** Resolved
**Severity:** High
**Reported:** 2026-01-18
**Resolved:** 2026-02-07
**Related:** [[User Feedback#Session-002]]
#### Description
When a Quote is converted to a Word (via swipe-right), the definition is set to "Converted from quote - tap to look up". However, tapping on the word in Session Detail did nothing.
#### Resolution
Implemented tap-to-relookup functionality:
1. Added `updateWord()` DAO method
2. Added `relookupWord()` function in `SessionViewModel` (Dictionary API → Wikipedia fallback)
3. Made undefined words tappable in `SwipeableWordItem`
4. Added "Tap to look up" hint text below undefined definitions
5. Once looked up successfully, word updates and is no longer tappable
---
### BUG-R008: Lock Screen Media Controls Inconsistent
**Status:** Resolved (Approach Changed)
**Severity:** Critical
**Reported:** 2026-01-18
**Resolved:** 2026-02-07
**Related:** [[Technical_Decisions#TDR-002]]
#### Description
The MediaSession "Trojan Horse" approach was unreliable due to Android platform restrictions:
- Notification shade wouldn't collapse
- Cold-start failures due to background activity launch restrictions
#### Resolution
**Abandoned MediaSession approach entirely.** Replaced with:
1. **Quick Settings Tile** (`QuickCaptureTileService`) as primary capture trigger
2. **Simplified foreground notification** with action buttons
3. Removed all `MediaSessionCompat` code from `ReadingSessionService`
4. Changed foreground service type from `mediaPlayback` to `specialUse`
This approach:
- Uses stable, system-supported APIs
- Works reliably from lock screen
- Simplifies codebase for future iOS port
- Trades one extra tap for 100% reliability
---
### BUG-R009: Play Button Shows Pause After Tap
**Status:** Resolved (No Longer Applicable)
**Severity:** Medium
**Reported:** 2026-01-18
**Resolved:** 2026-02-07
**Related:** [[#BUG-R008]]
#### Description
After tapping play button, the icon changed to pause and stayed that way.
#### Resolution
No longer applicable. MediaSession approach was removed entirely. The Quick Settings tile doesn't have this issue.
---
### BUG-R006: Book Detail View Crashes App
**Status:** Resolved
**Severity:** Critical
**Resolved:** 2026-01-24
**Device:** Pixel 10 Pro, Android 13
**Related:** [[Feature Backlog#Book Layer View]]
#### Description
Tapping a Book card in the Library view to open Book Detail crashed the application. Only the first book's sessions would load; others caused crashes.
#### Root Cause
In `ReviewScreen.kt`, the `LaunchedEffect` was collecting `Flow` emissions inside a `forEach` loop. The first `collect` call blocks indefinitely, preventing subsequent books from having their sessions loaded.
```kotlin
// BROKEN: collect blocks, only first book works
LaunchedEffect(books) {
books.forEach { bookWithMetrics ->
viewModel.database.vibeReaderDao()
.getRecentSessionsForBook(bookWithMetrics.book.bookId, 5)
.collect { sessions -> ... } // Blocks here!
}
}
```
#### Resolution
Wrapped each Flow collection in its own `launch {}` coroutine to run in parallel:
```kotlin
// FIXED: Each book gets its own coroutine
LaunchedEffect(books) {
books.forEach { bookWithMetrics ->
launch {
viewModel.database.vibeReaderDao()
.getRecentSessionsForBook(bookWithMetrics.book.bookId, 5)
.collect { sessions -> ... }
}
}
}
```
Added import: `import kotlinx.coroutines.launch`
---
### BUG-R004: Capture Activity Doesn't Re-launch After Close
**Status:** Resolved
**Severity:** Critical
**Resolved:** 2026-01-18
**Related:** [[User Feedback#Session-002]]
#### Description
After closing or dismissing the `SpeechCaptureActivity` (via Cancel, error state, or system back), subsequent attempts to trigger capture from the lock screen or notification did not restart listening.
#### Root Cause
The activity was launched with `FLAG_ACTIVITY_SINGLE_TOP`, which reuses existing instances. When the activity was already in the back stack but not destroyed, Android called `onNewIntent()` instead of `onCreate()`. Without an `onNewIntent()` handler, `startListening()` was never re-invoked.
Additionally, stale `SpeechRecognizer` state from the previous session was not being cleaned up when the activity went to background.
#### Resolution
1. Added `onNewIntent()` override that resets capture mode and calls `startListening()`
2. Added `onStop()` override that calls `speechRecognizer.stopListening()` and `speechRecognizer.cancel()`
```kotlin
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
setIntent(intent)
captureMode = /* parse from intent */
startListening()
}
override fun onStop() {
super.onStop()
speechRecognizer.stopListening()
speechRecognizer.cancel()
}
```
---
### BUG-R005: Quote-to-Word Conversion Crashes
**Status:** Resolved
**Severity:** High
**Resolved:** 2026-01-18
**Related:** [[User Feedback#Session-002]]
#### Description
Swiping right on a Quote to convert it to a Word occasionally caused a silent crash. No error shown to user; conversion simply didn't happen.
#### Root Cause
Unhandled exception during database operations. The conversion required both inserting a new Word and deleting the Quote, but if either operation failed, the entire transaction would fail silently.
#### Resolution
Wrapped conversion operations in try-catch blocks with error logging:
```kotlin
fun convertQuoteToWord(quote: Quote) {
viewModelScope.launch {
try {
dao.insertWord(Word(...))
dao.deleteQuote(quote)
} catch (e: Exception) {
Log.e("SessionViewModel", "Failed to convert quote to word", e)
}
}
}
```
---
### BUG-R001: Notification Buttons Invisible on Android 12+
**Status:** Resolved
**Severity:** Critical
**Resolved:** 2025-11-12
**Related:** Product Diary 2025-11-12
#### Description
Notification action buttons ("Define", "Quote", "End") were not visible on devices running Android 12+.
#### Root Cause
Android 12+ requires notification actions to have valid icon resources. Actions without icons are silently hidden by the OS.
#### Resolution
Added explicit icon resources to all notification actions:
```kotlin
.addAction(android.R.drawable.ic_menu_search, "Define", definePendingIntent)
.addAction(android.R.drawable.ic_input_add, "Quote", quotePendingIntent)
```
---
### BUG-R002: Button Tap "Glows" But Nothing Happens
**Status:** Resolved
**Severity:** High
**Resolved:** 2025-11-12
**Related:** Product Diary 2025-11-12
#### Description
Notification buttons showed visual feedback (glow animation) when tapped, but capture overlay did not appear.
#### Root Cause
Race condition: The UI was starting the Service and writing to the database simultaneously. The Service would wake up, query for active session, find nothing (DB write not yet committed), and exit.
#### Resolution
Passed `session_id` directly to the Service via Intent extra, removing dependency on database query timing.
---
### BUG-R003: Gradle/KSP Version Mismatch with Hilt
**Status:** Resolved (by removing Hilt)
**Severity:** High
**Resolved:** 2026-01-10
**Related:** [[Technical_Decisions#TDR-004]]
#### Description
Build failures with error: `ksp ... is too old for kotlin...`
#### Root Cause
Hilt's KSP processor version was incompatible with the project's Kotlin version. The Hilt → KSP → Kotlin version matrix is fragile.
#### Resolution
Removed Hilt entirely; switched to Manual DI / Singleton pattern. Build stability restored immediately.
---
## Issue Template
```markdown
### BUG-XXX: [Title]
**Status:** Open
**Severity:** [Critical/High/Medium/Low]
**Reported:** YYYY-MM-DD
**Device:** [Device + Android version]
**Related:** [[Link to related docs]]
#### Description
[What's happening]
#### Steps to Reproduce
1. Step one
2. Step two
3. **Expected:** [What should happen]
4. **Actual:** [What actually happens]
#### Root Cause
[Technical explanation if known]
#### Resolution
[How it was fixed, or workaround]
```
---
## Bug Metrics
| Status | Count |
|--------|-------|
| Open | 0 |
| In Progress | 0 |
| Resolved | 9 |
| Won't Fix | 0 |
| Severity | Open | Resolved |
|----------|------|----------|
| Critical | 0 | 5 |
| High | 0 | 3 |
| Medium | 0 | 1 |
| Low | 0 | 0 |