zeroclaw-labs/zeroclaw · error
tunnel.pinggy.region must be one of: us, eu, ap, br, au (or
Error message
tunnel.pinggy.region must be one of: us, eu, ap, br, au (or omitted for auto)
What it means
Validates tunnel.pinggy.region in Config::validate. When a Pinggy tunnel region is configured, it is trimmed and ASCII-lowercased, then must be one of the five supported Pinggy regions: us, eu, ap, br, au. An empty string after trim is allowed (means auto-selection), and case does not matter because of the lowercasing — only the region code itself must match. Any other value (country names, full words, unsupported regions) is rejected.
Source
Thrown at crates/zeroclaw-config/src/schema.rs:22056
"notion.input_property must not be empty"
);
}
if self.notion.result_property.trim().is_empty() {
validation_bail!(
RequiredFieldEmpty,
"notion.result_property",
"notion.result_property must not be empty"
);
}
}
// Pinggy tunnel region — validate allowed values (case-insensitive, auto-lowercased at runtime).
if let Some(ref pinggy) = self.tunnel.pinggy
&& let Some(ref region) = pinggy.region
{
let r = region.trim().to_ascii_lowercase();
if !r.is_empty() && !matches!(r.as_str(), "us" | "eu" | "ap" | "br" | "au") {
anyhow::bail!(
"tunnel.pinggy.region must be one of: us, eu, ap, br, au (or omitted for auto)"
);
}
}
// Jira
if self.jira.enabled {
if self.jira.base_url.trim().is_empty() {
anyhow::bail!("jira.base_url must not be empty when jira.enabled = true");
}
if self.jira.api_token.trim().is_empty()
&& std::env::var("JIRA_API_TOKEN")
.unwrap_or_default()
.trim()
.is_empty()
{
anyhow::bail!(
"jira.api_token must be set (or JIRA_API_TOKEN env var) when jira.enabled = true"View on GitHub (pinned to 88bb9c8533)
Solutions
- Change tunnel.pinggy.region to one of: us, eu, ap, br, au (case-insensitive)
- Or delete the region key entirely to let Pinggy auto-select the closest region
Example fix
# before [tunnel.pinggy] region = "us-east-1" # after [tunnel.pinggy] region = "us"
Defensive patterns
Strategy: validation
Validate before calling
const PINGGY_REGIONS: [&str; 5] = ["us", "eu", "ap", "br", "au"];
fn pinggy_region_ok(region: Option<&str>) -> bool {
match region {
None => true,
Some(r) => { let r = r.trim().to_ascii_lowercase(); r.is_empty() || PINGGY_REGIONS.contains(&r.as_str()) }
}
} Try / catch
if let Err(e) = cfg.validate() {
if e.to_string().contains("tunnel.pinggy.region") {
eprintln!("region must be us/eu/ap/br/au or omitted; got: {:?}", cfg.tunnel.pinggy.as_ref().and_then(|p| p.region.clone()));
}
} Prevention
- Use a config schema/enum for region in generated configs instead of free text
- Omit the region key when auto-selection is acceptable — fewer fields, fewer failures
When it happens
Trigger: Configuring tunnel.pinggy with `region = "usa"`, "japan", "in", "EU " (fine, lowercased) or any code outside {us, eu, ap, br, au}; passing a country code where a Pinggy region code is expected; typos like "au " are fine (trimmed) but "AUS" is not.
Common situations: User copies an AWS-style region string (e.g. "us-east-1") into the Pinggy config; user guesses a region Pinggy does not offer; values harvested from cloud provider configs pasted wholesale.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- jira.allowed_actions contains unknown action: '{}'. Valid: g
- matrix: `homeserver` is required
- Cannot persist empty Telegram identity
- transcription.max_audio_bytes must be greater than zero
- Edge TTS binary_path must be a bare command name without pat
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/7c3ab288a34ac706.
Report an issue: GitHub.