Hmbown/CodeWhale · error
unsupported Z.AI web-search endpoint
Error message
unsupported Z.AI web-search endpoint: {base_url} What it means
The Z.AI web-search adapter maps the configured base URL to the upstream search_engine parameter: api.z.ai maps to "search-prime" and open.bigmodel.cn maps to "search_std". Any other (or unrecognized) base URL has no known engine mapping, so build_body refuses the request instead of guessing an engine.
Solutions
- Set the provider base URL to exactly https://api.z.ai/api/paas/v4 or https://open.bigmodel.cn/api/paas/v4
- If using a proxy, add its normalized URL to the match arms in build_body with the correct search_engine
- Fix typos/extra path segments in the configured base URL
- Extend the mapping if Z.AI added a new official endpoint
Example fix
// before
_ => bail!("unsupported Z.AI web-search endpoint: {base_url}"),
// after: also accept a self-hosted proxy mapped to the standard engine
"https://zai-proxy.internal.example/api/paas/v4" => "search-prime",
_ => bail!("unsupported Z.AI web-search endpoint: {base_url}"), Defensive patterns
Strategy: validation
Validate before calling
const SUPPORTED: [&str; 2] = ["https://api.z.ai/api/paas/v4", "https://open.bigmodel.cn/api/paas/v4"];
assert!(SUPPORTED.contains(&base_url.trim_end_matches('/').to_ascii_lowercase().as_str()),
"unsupported Z.AI endpoint: {base_url}"); Try / catch
match build_body(&req, base_url) {
Err(e) if e.to_string().contains("unsupported Z.AI web-search endpoint") => {
eprintln!("{e}; defaulting to https://api.z.ai/api/paas/v4");
build_body(&req, "https://api.z.ai/api/paas/v4")
}
other => other,
} Prevention
- Copy base URLs exactly from provider docs, no trailing extras
- Normalize (lowercase, strip trailing '/') before storing config
- Add new official endpoints to the mapping before deploying them
When it happens
Trigger: build_body receives a base_url that, after trimming trailing slashes and lowercasing, matches neither "https://api.z.ai/api/paas/v4" nor "https://open.bigmodel.cn/api/paas/v4" — e.g. a custom proxy URL or a regional endpoint.
Common situations: Pointing the Z.AI provider at a self-hosted proxy or gateway URL; typo in the base URL; using a new Z.AI regional endpoint not yet in the mapping; trailing path differences like /api/paas/v4/ vs configured variants.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- 127
- A pinned task provider requires an explicit model
- active provider has no native web-search adapter
- agent profile reasoning_effort must be one of: inherit…
- approval log has no parent
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/a0e5a5c3a4291dea.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/client/provider_native_search/zai.rs:15
//! Z.AI and Zhipu structured Web Search API contracts.
use anyhow::{Result, bail};
use serde_json::{Value, json};
use super::{
ProviderNativeSearchRequest, ProviderNativeSearchResponse, citation_from_url, push_citation,
};
pub(super) fn build_body(request: &ProviderNativeSearchRequest, base_url: &str) -> Result<Value> {
let normalized = base_url.trim().trim_end_matches('/').to_ascii_lowercase();
let search_engine = match normalized.as_str() {
"https://api.z.ai/api/paas/v4" => "search-prime",
"https://open.bigmodel.cn/api/paas/v4" => "search_std",
_ => bail!("unsupported Z.AI web-search endpoint: {base_url}"),
};
Ok(json!({
"search_engine": search_engine,
"search_query": request.query,
"count": request.max_results,
}))
}
pub(super) fn parse(payload: &Value) -> ProviderNativeSearchResponse {
let mut citations = Vec::new();
if let Some(results) = payload.get("search_result").and_then(Value::as_array) {
for result in results {
let Some(url) = result.get("link").and_then(Value::as_str) else {
continue;
};
let title = result
.get("title")
.and_then(Value::as_str)View on GitHub (pinned to 73e0f67d83)