fix: resolve speech-to-text crashes and post-API-key error storm #4738
ccantynzcommented Jun 15, 2026
Originally written by @vercel[bot] on GitHub.
The latest updates on your projects. Learn more about Vercel for GitHub.
| Project | Deployment | Actions | Updated (UTC) |
|---|---|---|---|
| voxlen | Preview, Comment | Jun 15, 2026 9:18am |
Cross-repo impact
See what breaks downstream if this PR merges.
⮌ Merged
This pull request was merged into main.
c comment · e edit title · m merge · a approve · r request changes · ? shortcuts
Originally written by @ccantynz-alt on GitHub.
Imported from https://github.com/ccantynz-alt/voxlen/pull/63
Problem
Users reported: "after installing the API code and going to use the product it just crashes with lots of errors." I spawned three parallel investigation agents (Rust backend, React/TS frontend, and the end-to-end API-key flow) to trace the crashes.
Root cause
API keys are stored only in the OS keychain (for privacy) and were never loaded back into the Rust backend at startup. So on the next launch — or if the user dictated before a 500 ms debounce fired — the backend had no key. The first dictation failed with
No API key configured, and the streaming layer then entered an endless reconnect storm, emitting a flood of error/reconnect toasts. That's the literal "lots of errors." Several latent runtime panics in the audio/STT pipeline compounded it.Fixes
Backend (
src-tauri)load_settings_from_disknow readssttApiKey/grammarApiKey/voxlenApiKeyback from the OS keychain so engines have the keys before the first hotkey. Newkeyring::read_secret()degrades gracefully when there's no keychain backend (headless Linux).idx_floorinresample()andsimple_resample(); upsampling from a low-rate device (8 kHz telephony / Bluetooth HFP) indexed past the buffer end and panicked.sample_rate/channels == 0(misreporting / virtual devices).== 0up front (was a CPU-spin / apparent freeze).String::truncatepanicked mid-codepoint on localized names).Frontend (
src)/api/mepayload shape before readingplan/features; a malformed HTTP 200 threw during render and crashed the app right after connecting a key.Testing
cargo checkclean; new Rust regression tests for resample upsampling and UTF-8 device-name truncation pass.tsc --noEmitclean; all 178 frontend tests pass.Not yet addressed (follow-ups identified by the agents)
https://claude.ai/code/session_016YZd5wbQ9H1tmr1DZT4MpF
Generated by Claude Code