zeroclaw-labs/zeroclaw · error · anyhow::Error
grok_cli env_passthrough entry `{name}` is provider-owned (`
Error message
grok_cli env_passthrough entry `{name}` is provider-owned (`XAI_*` other than `XAI_API_KEY`, and all `GROK_*`); other names (for example tool credentials) may be listed explicitly, and Grok CLI policy flags belong in `extra_args` What it means
env_passthrough blocks provider-owned names: every GROK_* variable and all XAI_* except XAI_API_KEY, because ZeroClaw injects those itself and a passthrough entry would fight the provider. Other names (e.g. tool credentials) are explicitly allowed; Grok CLI policy flags belong in extra_args, not env.
Source
Thrown at crates/zeroclaw-providers/src/grok_cli.rs:526
"grok_cli max_acp_stdout_bytes must be between {} and {} bytes",
acp::MIN_ACP_STDOUT_LIMIT_BYTES,
acp::MAX_ACP_STDOUT_LIMIT_BYTES
);
}
Ok(limit)
}
fn normalize_and_validate_env_passthrough(names: Vec<String>) -> anyhow::Result<Vec<String>> {
let mut normalized: Vec<String> = Vec::with_capacity(names.len());
for name in names {
let name = name.trim();
if !is_valid_env_var_name(name) {
anyhow::bail!(
"grok_cli env_passthrough entry `{name}` is invalid; expected [A-Za-z_][A-Za-z0-9_]*"
);
}
if is_disallowed_provider_env_var(name) {
anyhow::bail!(
"grok_cli env_passthrough entry `{name}` is provider-owned \
(`XAI_*` other than `XAI_API_KEY`, and all `GROK_*`); \
other names (for example tool credentials) may be listed \
explicitly, and Grok CLI policy flags belong in `extra_args`"
);
}
if !normalized
.iter()
.any(|existing| env_names_equal(existing.as_str(), name))
{
// Preserve the operator-supplied spelling; equality is
// case-insensitive on Windows when checking membership later.
normalized.push(name.to_string());
}
}
Ok(normalized)
}
View on GitHub (pinned to 88bb9c8533)
Solutions
- Remove the provider-owned entry; configure the equivalent behavior through provider fields or extra_args
- Keep XAI_API_KEY in env_passthrough only if the key must come from the environment
- For tool credentials (non-provider names), leave them listed - they are allowed
Example fix
# before env_passthrough = ["XAI_API_KEY", "GROK_MODEL", "PATH"] # after env_passthrough = ["XAI_API_KEY", "PATH"] # model goes in the model field / extra_args
Defensive patterns
Strategy: validation
Validate before calling
fn is_provider_owned_env(name: &str) -> bool {
let n = name.to_ascii_uppercase();
n.starts_with("GROK_") || (n.starts_with("XAI_") && n != "XAI_API_KEY")
}
fn passthrough_entry_allowed(name: &str) -> bool {
valid_env_var_name(name) && !is_provider_owned_env(name)
} Type guard
fn is_provider_owned_env(name: &str) -> bool {
let n = name.to_ascii_uppercase();
n.starts_with("GROK_") || (n.starts_with("XAI_") && n != "XAI_API_KEY")
} Prevention
- Keep provider policy in extra_args and provider fields, never env
- When porting shell wrappers, strip all GROK_*/XAI_* exports except XAI_API_KEY
- Re-run config lint after grok_cli version upgrades that add provider vars
When it happens
Trigger: Listing XAI_API_TIMEOUT, XAI_BASE_URL, or GROK_MODEL in env_passthrough; migrating a manual grok CLI invocation that exported GROK_* vars and keeping them in the passthrough list.
Common situations: Ported shell wrappers; attempts to override model or policy through environment instead of config; security reviews tightening env hygiene.
Related errors
- grok_cli env_passthrough entry `{name}` is invalid; expected
- risk_profiles.{profile_alias}.shell_env_passthrough[{i}] is
- grok_cli requires an explicit working_directory for the ACP
- grok_cli working_directory must be an absolute path
- grok_cli working_directory must identify a directory
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/899ad18ba7311469.
Report an issue: GitHub.