{"record":{"id":"e4fcc7f7349e27fd","repo":"tonhowtf/omniget","slug":"describe","errorCode":null,"errorMessage":"describe: {}","messagePattern":"describe: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src-tauri/omniget-core/src/core/tools/voicestudio.rs","lineNumber":401,"sourceCode":"    pub unmatched: Vec<String>,\n    pub profile_id: Option<String>,\n}\n\n/// Descrição em texto → atributos → voz nova falando o texto.\npub async fn design_speak(\n    opts: DesignOptions,\n    progress: super::ProgressFn,\n) -> anyhow::Result<DesignResult> {\n    let b = base(&opts.base_url);\n    let c = client(900)?;\n    super::report(&progress, \"voicestudio\", \"describe\", 0, None, None);\n    let j: serde_json::Value = c\n        .post(format!(\"{}/design/describe\", b))\n        .json(&serde_json::json!({ \"description\": opts.description }))\n        .send()\n        .await?\n        .error_for_status()\n        .map_err(|e| anyhow!(\"describe: {}\", e))?\n        .json()\n        .await?;\n    let instruct = j\n        .get(\"instruct\")\n        .and_then(|v| v.as_str())\n        .unwrap_or(\"\")\n        .to_string();\n    let matched: Vec<String> = j\n        .get(\"matched\")\n        .and_then(|v| v.as_array())\n        .map(|a| {\n            a.iter()\n                .filter_map(|m| m.get(\"phrase\").and_then(|p| p.as_str()).map(String::from))\n                .collect()\n        })\n        .unwrap_or_default();\n    let unmatched: Vec<String> = j\n        .get(\"unmatched\")","sourceCodeStart":383,"sourceCodeEnd":419,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/omniget-core/src/core/tools/voicestudio.rs#L383-L419","documentation":"design_speak POSTs the natural-language description to {base}/design/describe and calls error_for_status(); any non-success response is wrapped as 'describe: {}'. It means the server rejected the voice-design description request that produces the synthesis instruct parameters.","triggerScenarios":"POST /design/describe returns 4xx/5xx: empty or overly long description text, invalid auth, unknown design endpoint, or a server error while interpreting the description.","commonSituations":"User submitted a blank description (opts.description empty), API token missing/expired, VoiceStudio backend updated the /design route, or rate limiting on the describe endpoint.","solutions":["Check the wrapped status in the error: 401/403 → credentials; 400/422 → description content.","Ensure opts.description is non-empty and within the server's length limits before calling.","Verify API key and base URL configuration.","Confirm the VoiceStudio version still exposes /design/describe (endpoint may have changed).","Retry with backoff on 429/5xx."],"exampleFix":"// before\nlet j: serde_json::Value = c\n    .post(format!(\"{}/design/describe\", b))\n    .json(&serde_json::json!({ \"description\": opts.description }))\n    .send()\n    .await?\n    .error_for_status()\n    .map_err(|e| anyhow!(\"describe: {}\", e))?;\n// after\nanyhow::ensure!(!opts.description.trim().is_empty(), \"describe: descricao vazia\");\nlet resp = c.post(format!(\"{}/design/describe\", b))\n    .json(&serde_json::json!({ \"description\": opts.description }))\n    .send().await?;\nlet j: serde_json::Value = resp.error_for_status()\n    .map_err(|e| anyhow!(\"describe: {}\", e))?\n    .json().await?;","handlingStrategy":"validation","validationCode":"let desc = opts.description.trim();\nif desc.is_empty() {\n    return Err(\"description must not be empty\".into());\n}\nif desc.len() > 2000 {\n    return Err(\"description too long\".into());\n}","typeGuard":null,"tryCatchPattern":"match design_result {\n    Err(e) if e.to_string().contains(\"describe:\") => {\n        let s = e.to_string();\n        if s.contains(\"401\") || s.contains(\"403\") { /* refresh API key */ }\n        else if s.contains(\"404\") { /* endpoint changed: check VoiceStudio version */ }\n        else if s.contains(\"429\") || s.contains(\"50\") { /* backoff and retry */ }\n        else { /* surface to user */ }\n    }\n    other => other?,\n}","preventionTips":["Require a non-empty, bounded-length description in the UI before submission.","Verify API credentials before design operations.","Pin/verify the VoiceStudio server version exposing /design/describe.","Apply backoff on rate-limited or 5xx describe responses."],"tags":["http","api","network","rust"],"backgroundTag":"http-error-response","analyzedSha":"8600b91f4246848bac346874daa9e61c1fc5677a","analyzedAt":"2026-09-12T14:29:19.317Z","contentChangedAt":"2026-09-12T14:29:19.317Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}