{"record":{"id":"2759cadf1866c5ec","repo":"Hmbown/CodeWhale","slug":"speech-text-cannot-be-empty-2759ca","errorCode":null,"errorMessage":"Speech text cannot be empty","messagePattern":"Speech text cannot be empty","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/tui/src/lib.rs","lineNumber":7362,"sourceCode":"        output_dir,\n        model,\n        voice,\n        instruction,\n        voice_prompt,\n        clone_voice,\n        format,\n        json: json_output,\n    } = args;\n\n    if config.api_provider() != ApiProvider::XiaomiMimo {\n        bail!(\n            \"`speech` requires provider = \\\"xiaomi-mimo\\\" (current: {}). Run with `--provider xiaomi-mimo` or set it in config.\",\n            config.api_provider().as_str()\n        );\n    }\n\n    if text.trim().is_empty() {\n        bail!(\"Speech text cannot be empty\");\n    }\n    let voice_is_data_uri = voice\n        .as_deref()\n        .map(str::trim)\n        .is_some_and(|value| value.starts_with(\"data:audio/\"));\n    if clone_voice.is_some() && voice.is_some() {\n        bail!(\"Use either --clone-voice or --voice for cloned voice data, not both\");\n    }\n    let model = infer_speech_model(\n        model.as_deref(),\n        clone_voice.is_some() || voice_is_data_uri,\n        voice_prompt.is_some(),\n    );\n    let model_lower = model.to_ascii_lowercase();\n    if !model_lower.contains(\"tts\") {\n        bail!(\n            \"speech requires a TTS model (examples: {}); got {model}\",\n            SPEECH_MODEL_EXAMPLES.join(\", \")","sourceCodeStart":7344,"sourceCodeEnd":7380,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/0c42157ee52f9d55af2b506d71b46249910f77d3/crates/tui/src/lib.rs#L7344-L7380","documentation":"Basic input guard in the speech command: after the provider check it trims the text argument and refuses whitespace-only input. A TTS request with empty text is meaningless (and would fail server-side), so the CLI rejects it before touching the network or inferring a model.","triggerScenarios":"Invoking `codewhale speech` with a text argument that is empty or only whitespace (text.trim().is_empty()).","commonSituations":"Passing an unset shell variable (empty after expansion); scripts generating text from a template that rendered blank; copy-paste losing the quoted argument.","solutions":["Pass a non-empty text string — leading/trailing whitespace alone is not enough","If text comes from a variable, assert it is set and non-blank before invoking","When text is generated, check the generator/template that produced the blank output"],"exampleFix":"// before\nTEXT=\"\"\ncodewhale speech --text \"$TEXT\"   # bails: Speech text cannot be empty\n\n// after\nTEXT=\"Build 42 finished\"\n[ -n \"$(printf '%s' \"$TEXT\" | tr -d '[:space:]')\" ] && codewhale speech --text \"$TEXT\"","handlingStrategy":"validation","validationCode":"# reject blank text before calling the CLI\n[ -n \"$(printf '%s' \"$TEXT\" | tr -d '[:space:]')\" ] || { echo 'speech text is blank' >&2; exit 2; }\ncodewhale speech --text \"$TEXT\"","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Default-expand variables with : \"${VAR:?msg}\" so empty input fails at the script boundary","Validate generated speech text at the producer, not at the CLI"],"tags":["speech","validation","empty-input"],"backgroundTag":"empty-required-input","analyzedSha":"0c42157ee52f9d55af2b506d71b46249910f77d3","analyzedAt":"2026-08-20T21:50:45.477Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}