tinyhumansai/openhuman · error
audio blob is empty
Error message
audio blob is empty
What it means
Required-flag error from `openhuman memory query`. After the parsing loop, `--namespace` was never supplied. Unlike ingest (which defaults to namespace 'cli'), query deliberately has no namespace default — you must name the namespace to search explicitly.
Source
Thrown at app/src/features/human/voice/wavEncoder.ts:23
*
* Why this exists: the hosted STT upstream (GMI Whisper) rejects
* Opus-in-WebM payloads with "Invalid JSON payload", and Chromium-based
* runtimes (including the CEF webview Tauri ships) don't reliably support
* `MediaRecorder` with MP4. WAV at Whisper's native 16kHz is the most
* portable thing we can hand the backend without standing up an ffmpeg
* dependency in the desktop app.
*
* Implementation: `OfflineAudioContext` decodes + resamples in one pass,
* then we mix to mono and write a standard RIFF/WAVE header in front of
* the 16-bit little-endian samples. Synchronous after the decode promise
* resolves so we can pipe it straight into the STT client.
*/
const TARGET_SAMPLE_RATE = 16_000;
export async function encodeBlobToWav(blob: Blob): Promise<Blob> {
if (!blob || blob.size === 0) {
throw new Error('audio blob is empty');
}
const arrayBuffer = await blob.arrayBuffer();
// `decodeAudioData` consumes the buffer, so use a copy if the caller
// happens to reuse `blob` afterwards.
const decoded = await decodeToBuffer(arrayBuffer.slice(0));
const mono = mixDownToMono(decoded);
const wav = buildWav(mono, TARGET_SAMPLE_RATE);
return new Blob([wav], { type: 'audio/wav' });
}
/**
* Decode arbitrary compressed audio into an `AudioBuffer` at
* `TARGET_SAMPLE_RATE`. Uses `OfflineAudioContext` so the resample
* happens during decode rather than via a separate render step.
*/
async function decodeToBuffer(arrayBuffer: ArrayBuffer): Promise<AudioBuffer> {
// OfflineAudioContext requires concrete length/channels up front, but
// `decodeAudioData` returns a buffer at the source rate. Trick: decodeView on GitHub (pinned to a221052e0d)
Solutions
- Add `-n/--namespace <ns>` to the query command
- List existing namespaces first with `openhuman memory namespaces`
- In scripts, fail fast when the namespace variable is empty instead of silently dropping the flag
Example fix
# before openhuman memory query --query "hello" # after openhuman memory namespaces # pick a ns, then: openhuman memory query --namespace cli --query "hello"
Defensive patterns
Strategy: validation
Validate before calling
# bash: refuse to invoke query without a namespace
[ -n "${NS:-}" ] || { echo '--namespace is required for query' >&2; exit 2; }
openhuman memory query --namespace "$NS" --query "$Q" Try / catch
if ! out=$(openhuman memory query "$@" 2>&1); then case "$out" in *"--namespace is required"*) openhuman memory namespaces >&2; exit 2;; esac printf '%s\n' "$out" >&2; exit 1 fi
Prevention
- Do not assume ingest's 'cli' default applies to query — it does not
- Discover valid namespaces with `openhuman memory namespaces` before scripting queries
When it happens
Trigger: `openhuman memory query --query "hello"` (query given, namespace missing); `openhuman memory query -v`; a script that only passes -q because the author assumed the ingest default applies to query too.
Common situations: Assuming the 'cli' default from ingest carries over to query; scripts where the namespace variable is empty and the flag is conditionally skipped; exploring a fresh workspace and not knowing which namespaces exist.
Related errors
- OpenHuman could not reach its local runtime. Quit and reopen
- audio blob is empty
- voice_not_compiled
- Recovery phrase is required.
- Failed to secure recovery phrase. Please try again.
AI-assisted analysis of tinyhumansai/openhuman@a221052e0d (2026-08-16).
Data as JSON: /api/errors/d2719d1c3df3759c.
Report an issue: GitHub.