Skip to content

fix(voice): friendly STT error with direct settings link#761

Merged
graycyrus merged 2 commits into
tinyhumansai:mainfrom
graycyrus:fix/friendly-voice-stt-error
Apr 22, 2026
Merged

fix(voice): friendly STT error with direct settings link#761
graycyrus merged 2 commits into
tinyhumansai:mainfrom
graycyrus:fix/friendly-voice-stt-error

Conversation

@graycyrus
Copy link
Copy Markdown
Contributor

@graycyrus graycyrus commented Apr 22, 2026

Summary

  • Replace technical "whisper.cpp binary not found. Set WHISPER_BIN or install whisper-cli" error with user-friendly message: "Voice input needs a speech model. Go to Settings to download one."
  • Add a "Set up" button in the error banner that navigates directly to /settings/local-model so users can download the STT model in one click
  • Detect whisper/binary-related transcription failures and map them to the friendly stt_not_ready error code

Test plan

  • Trigger voice transcription without whisper/STT model installed (via dictation hotkey)
  • Verify friendly error message appears instead of technical whisper.cpp error
  • Click "Set up" link — should navigate to /settings/local-model
  • Click "Dismiss" — error clears normally
  • yarn typecheck passes
  • yarn lint passes

Summary by CodeRabbit

  • Bug Fixes
    • Enhanced error messages for voice transcription failures and unavailable speech-to-text services with clearer setup guidance
    • Added "Set Up" button to voice-related error notifications, allowing users to quickly navigate to speech model configuration
    • Improved error categorization for better identification and communication of setup-related voice feature issues

@graycyrus graycyrus requested a review from a team April 22, 2026 06:44
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 22, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 0724ac25-2b6e-4e77-a6cd-8412eb9a4c86

📥 Commits

Reviewing files that changed from the base of the PR and between 1aea77d and a894f9a.

📒 Files selected for processing (2)
  • app/src/chat/chatSendError.ts
  • app/src/pages/Conversations.tsx
✅ Files skipped from review due to trivial changes (1)
  • app/src/chat/chatSendError.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • app/src/pages/Conversations.tsx

📝 Walkthrough

Walkthrough

The changes extend the error categorization system to handle speech-to-text readiness failures by adding a new 'stt_not_ready' error code, and update the Conversations UI to intelligently classify STT-related errors, display appropriate messaging, and provide users a navigation pathway to configure required models.

Changes

Cohort / File(s) Summary
Error Code Definition
app/src/chat/chatSendError.ts
Added 'stt_not_ready' union member to ChatSendErrorCode type to categorize speech-to-text readiness failures.
Voice UI Error Handling
app/src/pages/Conversations.tsx
Updated STT unavailability messaging, added error classification logic to detect STT setup issues (whisper/binary/model-related errors) and map them to the new stt_not_ready code; added conditional "Set up" button that navigates to /settings/local-model for both stt_not_ready and voice_transcription errors alongside a "Dismiss" option.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~15 minutes

Possibly related PRs

Poem

🐰 A whisper of sound, a model to find,
When STT stumbles, we're one step behind,
But now with clear errors and buttons so bright,
Setup's just a click—hop towards the light! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix(voice): friendly STT error with direct settings link' directly and accurately summarizes the main changes: improving STT error messaging and adding a settings navigation feature.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@app/src/pages/Conversations.tsx`:
- Around line 1267-1268: The current JSX conditional in Conversations.tsx that
checks sendError.code includes 'voice_transcription' and causes the "Set up" CTA
to appear for non-setup transcription failures; update the conditional that
renders the "Set up" link/button to only include the setup-specific code
'stt_not_ready' (remove 'voice_transcription' from the OR check on
sendError.code), and handle 'voice_transcription' separately (e.g., render a
different error message or retry option) so only genuine setup errors in the
sendError.code branch trigger the setup flow.
- Around line 493-496: The current isSetupIssue check uses case-sensitive
message.includes(...) calls and can miss mixed-case backend messages; modify the
logic that computes isSetupIssue (the variable using message) to perform
case-insensitive matching by normalizing the message (e.g., const txt =
message.toLowerCase()) and then checking txt.includes('whisper'),
txt.includes('binary not found'), and txt.includes('stt model') or use
case-insensitive regexes; update any references to isSetupIssue accordingly.

In `@src/openhuman/channels/proactive.rs`:
- Around line 110-113: The change forces thread_id to "default-thread" and emits
"chat_done", which breaks the frontend's proactive routing that listens for
"proactive_message" and "proactive:*" thread IDs; revert the emission to
"proactive_message" (instead of "chat_done") and stop hardcoding thread_id —
either preserve the incoming proactive thread id or construct a "proactive:{id}"
pattern (use the existing thread_id variable rather than "default-thread") so
the frontend's ChatService/ChatRuntimeProvider can route the event correctly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 069653e9-7797-4c5d-9089-79eff02793bb

📥 Commits

Reviewing files that changed from the base of the PR and between 758958b and 1aea77d.

📒 Files selected for processing (5)
  • app/src/chat/chatSendError.ts
  • app/src/pages/Conversations.tsx
  • src/openhuman/app_state/mod.rs
  • src/openhuman/app_state/ops.rs
  • src/openhuman/channels/proactive.rs

Comment on lines +493 to +496
const isSetupIssue =
message.includes('whisper') ||
message.includes('binary not found') ||
message.includes('STT model');
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Make setup-error detection case-insensitive.

Line 494-Line 496 use case-sensitive includes(...); mixed-case backend messages can be misclassified and miss the setup recovery path.

Suggested fix
       const message = err instanceof Error ? err.message : String(err);
+      const normalizedMessage = message.toLowerCase();
       const isSetupIssue =
-        message.includes('whisper') ||
-        message.includes('binary not found') ||
-        message.includes('STT model');
+        normalizedMessage.includes('whisper') ||
+        normalizedMessage.includes('binary not found') ||
+        normalizedMessage.includes('stt model');
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const isSetupIssue =
message.includes('whisper') ||
message.includes('binary not found') ||
message.includes('STT model');
const normalizedMessage = message.toLowerCase();
const isSetupIssue =
normalizedMessage.includes('whisper') ||
normalizedMessage.includes('binary not found') ||
normalizedMessage.includes('stt model');
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/src/pages/Conversations.tsx` around lines 493 - 496, The current
isSetupIssue check uses case-sensitive message.includes(...) calls and can miss
mixed-case backend messages; modify the logic that computes isSetupIssue (the
variable using message) to perform case-insensitive matching by normalizing the
message (e.g., const txt = message.toLowerCase()) and then checking
txt.includes('whisper'), txt.includes('binary not found'), and txt.includes('stt
model') or use case-insensitive regexes; update any references to isSetupIssue
accordingly.

Comment on lines +1267 to +1268
{(sendError.code === 'stt_not_ready' ||
sendError.code === 'voice_transcription') && (
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Show “Set up” only for setup-specific errors.

Line 1267-Line 1268 currently includes voice_transcription, which also represents non-setup failures. That can send users to model setup for unrelated transcription errors.

Suggested fix
-                {(sendError.code === 'stt_not_ready' ||
-                  sendError.code === 'voice_transcription') && (
+                {sendError.code === 'stt_not_ready' && (
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
{(sendError.code === 'stt_not_ready' ||
sendError.code === 'voice_transcription') && (
{sendError.code === 'stt_not_ready' && (
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/src/pages/Conversations.tsx` around lines 1267 - 1268, The current JSX
conditional in Conversations.tsx that checks sendError.code includes
'voice_transcription' and causes the "Set up" CTA to appear for non-setup
transcription failures; update the conditional that renders the "Set up"
link/button to only include the setup-specific code 'stt_not_ready' (remove
'voice_transcription' from the OR check on sendError.code), and handle
'voice_transcription' separately (e.g., render a different error message or
retry option) so only genuine setup errors in the sendError.code branch trigger
the setup flow.

Comment thread src/openhuman/channels/proactive.rs Outdated
Comment on lines +110 to +113
// Use "default-thread" so the message appears in the user's
// visible conversation thread (matches DEFAULT_THREAD_ID in
// the frontend Conversations page).
let thread_id = "default-thread".to_string();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Proactive event contract change is likely to break frontend proactive routing.

Line 127 switches emission to chat_done, and Line 113 forces default-thread. The current frontend proactive flow still listens for proactive_message and resolves proactive:* thread IDs (app/src/services/chatService.ts and app/src/providers/ChatRuntimeProvider.tsx snippets provided). This can bypass/detach the existing proactive dispatch path.

Suggested fix
-        // Use "default-thread" so the message appears in the user's
-        // visible conversation thread (matches DEFAULT_THREAD_ID in
-        // the frontend Conversations page).
-        let thread_id = "default-thread".to_string();
+        // Preserve proactive thread semantics expected by frontend routing.
+        let thread_id = format!("proactive:{}", job_name.as_deref().unwrap_or("system"));

@@
-        // Emit as `chat_done` so the existing frontend chat handlers
-        // pick it up — no dedicated `proactive_message` listener needed.
+        // Emit proactive event for dedicated proactive frontend handling.
         publish_web_channel_event(WebChannelEvent {
-            event: "chat_done".to_string(),
+            event: "proactive_message".to_string(),

Also applies to: 124-127

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/openhuman/channels/proactive.rs` around lines 110 - 113, The change
forces thread_id to "default-thread" and emits "chat_done", which breaks the
frontend's proactive routing that listens for "proactive_message" and
"proactive:*" thread IDs; revert the emission to "proactive_message" (instead of
"chat_done") and stop hardcoding thread_id — either preserve the incoming
proactive thread id or construct a "proactive:{id}" pattern (use the existing
thread_id variable rather than "default-thread") so the frontend's
ChatService/ChatRuntimeProvider can route the event correctly.

…missing

Replace technical "whisper.cpp binary not found" error with a user-friendly
message and a "Set up" link that navigates directly to Settings > Local AI
Models so non-technical users can easily download the required speech model.
@graycyrus graycyrus force-pushed the fix/friendly-voice-stt-error branch from 1aea77d to a894f9a Compare April 22, 2026 06:52
@graycyrus graycyrus merged commit 100b5b7 into tinyhumansai:main Apr 22, 2026
7 of 8 checks passed
AusAgentSmith pushed a commit to AusAgentSmith/openhuman that referenced this pull request May 23, 2026
…i#761)

* fix(voice): show friendly error with settings link when STT model is missing

Replace technical "whisper.cpp binary not found" error with a user-friendly
message and a "Set up" link that navigates directly to Settings > Local AI
Models so non-technical users can easily download the required speech model.

* style: apply prettier formatting
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant