tinyhumansai/openhuman · error · VoiceNotCompiledError
voice_not_compiled
voice_not_compiled
Error message
Voice transcription is unavailable in this build — the voice module was not compiled into the app. Update OpenHuman to the latest version; restarting will not help.
What it means
VoiceNotCompiledError (code 'voice_not_compiled') is thrown by transcribeCloud() when the JSON-RPC call to openhuman.voice_transcribe (or sibling voice_* method) fails with an 'unknown method' error. That response means the running core binary was compiled without the `voice` Cargo feature, so the voice controllers were never registered. As the comment explains, this is a compile-time property of the binary — restarting cannot fix it (the historical case: voice shipped missing from v0.58.19 to v0.61.x, issue #4901).
Solutions
- End user: update OpenHuman to the latest version — the fixed builds forward the voice feature again; restarting the current version will not help.
- Developer building the core: ensure the voice feature is enabled (product-features set) — check `scripts/ci/product-features.txt` forwarding and the Feature Forwarding Gate.
- Renderer: catch VoiceNotCompiledError (code 'voice_not_compiled') and hide/disable the voice UI with the 'update required' message instead of surfacing a raw failure.
- Verify with GET /schema on the core's RPC port that voice.* namespaces are listed before enabling voice features.
Example fix
// before
const text = await transcribeCloud(blob);
// after
try {
const text = await transcribeCloud(blob);
} catch (err) {
if (err instanceof VoiceNotCompiledError) {
renderVoiceDisabledNotice(); // 'Update OpenHuman' UI
return;
}
throw err;
} Defensive patterns
Strategy: try-catch
Validate before calling
import { callCoreRpc } from '../services/coreRpcClient';
// probe once at startup: does the core expose voice methods?
const voiceAvailable = await callCoreRpc<{ methods: string[] }>({ method: 'openhuman.schema' })
.then((s) => s.methods.some((m) => m.startsWith('openhuman.voice_')))
.catch(() => false); Type guard
function isVoiceNotCompiledError(e: unknown): boolean {
return e instanceof Error && (e as { code?: string }).code === 'voice_not_compiled';
} Try / catch
try {
text = await transcribeCloud(blob);
} catch (err) {
if (isVoiceNotCompiledError(err)) {
renderVoiceDisabledNotice(); // 'Update OpenHuman' — restart won't help
return;
}
throw err;
} Prevention
- Feature-detect voice_* methods via /schema at startup and disable voice UI proactively.
- Keep core and renderer versions in lockstep (no partial updates).
- If building the core yourself, always run the Feature Forwarding Gate before shipping.
When it happens
Trigger: The renderer calls callCoreRpc({method:'openhuman.voice_stt_transcribe'...}) against a core whose DomainSet/feature set omitted voice — e.g. a custom --no-default-features build, a distro/CI build missing the voice feature flag, or a version range where voice was accidentally not forwarded to the desktop shell (the #4901 regression).
Common situations: Users on app versions v0.58.19–v0.61.x where the voice gate was not forwarded to the shell; developers building openhuman-core manually without the voice feature; a slim/embedded core profile (DomainSet without voice) being reused by the full desktop renderer.
Related errors
- Core RPC returned an error
- audio blob is empty
- Local model runtime is unavailable in this core build…
- rpc_http transport was requested but this build was…
- At least one of --expression, --tz, --command, or --name…
AI-assisted analysis of tinyhumansai/openhuman@7491200858 (2026-08-17).
Data as JSON: /api/errors/e420f837f6bc777e.
Report an issue: GitHub.
Appendix: source
Thrown at app/src/features/human/voice/sttClient.ts:122
const rpcStart = Date.now();
let result: CloudTranscribeResult;
try {
result = await callCoreRpc<CloudTranscribeResult>({
method: 'openhuman.voice_cloud_transcribe',
params,
});
} catch (err) {
// An "unknown method" error means the core serving this app was built
// without the `voice` Cargo feature, so the `openhuman.voice_*`
// controllers were never registered (#4901). This is a compile-time
// property of the binary — restarting cannot change it, which is why the
// old #1289-era "restart to pick up the latest core sidecar" copy was
// unactionable (and the sidecar itself is gone since #1061).
const msg = err instanceof Error ? err.message : String(err);
if (msg.includes('unknown method')) {
sttLog('[voice-stt] transcribe rpc: voice domain absent from core build: %s', msg);
throw new VoiceNotCompiledError();
}
sttLog('transcribe rpc failed (passthrough): %O', err);
throw err;
}
const text = result?.text?.trim() ?? '';
sttLog('transcribed chars=%d rpc_ms=%d', text.length, Math.round(Date.now() - rpcStart));
return text;
}
interface FactoryTranscribeOptions {
/** BCP-47 language hint, e.g. `'en'`. */
language?: string;
/** Override the server-side provider resolution: `'cloud'` for the backend
* proxy, or a `voice_providers` slug. When unset the core resolves
* `voice_server.stt_engine`. */
provider?: string;
/** Model id for the selected engine (e.g. `'whisper-1'`, `'scribe_v1'`). */
model?: string;View on GitHub (pinned to 7491200858)