zeroclaw-labs/zeroclaw · error · anyhow::Error
grok_cli max_acp_stdout_bytes must be between {} and {} byte
Error message
grok_cli max_acp_stdout_bytes must be between {} and {} bytes What it means
max_acp_stdout_bytes caps the ACP stdout reader and must lie in [1_048_576, 67_108_864] bytes (1 MiB to 64 MiB); the default is 4 MiB. The minimum equals MAX_ACP_FRAME_BYTES so no single valid ACP frame is ever rejected by the cap.
Source
Thrown at crates/zeroclaw-providers/src/grok_cli.rs:507
);
}
let path = Path::new(trimmed);
if !path.is_absolute() {
anyhow::bail!("grok_cli working_directory must be an absolute path");
}
let canonical = std::fs::canonicalize(path).map_err(|_| {
anyhow::Error::msg("grok_cli working_directory does not exist or is inaccessible")
})?;
if !canonical.is_dir() {
anyhow::bail!("grok_cli working_directory must identify a directory");
}
Ok(canonical)
}
fn validate_acp_stdout_limit(value: Option<usize>) -> anyhow::Result<usize> {
let limit = value.unwrap_or(acp::DEFAULT_ACP_STDOUT_LIMIT_BYTES);
if !(acp::MIN_ACP_STDOUT_LIMIT_BYTES..=acp::MAX_ACP_STDOUT_LIMIT_BYTES).contains(&limit) {
anyhow::bail!(
"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) {View on GitHub (pinned to 88bb9c8533)
Solutions
- Choose a value within 1_048_576..=67_108_864 bytes
- Omit the option to accept the 4 MiB default
- Raise toward 64 MiB only when frames are genuinely larger
Example fix
# before max_acp_stdout_bytes = 65536 # after max_acp_stdout_bytes = 8388608 # 8 MiB, within [1 MiB, 64 MiB]
Defensive patterns
Strategy: validation
Validate before calling
const ACP_MIN: usize = 1_048_576;
const ACP_MAX: usize = 67_108_864;
fn stdout_limit_ok(v: usize) -> bool { (ACP_MIN..=ACP_MAX).contains(&v) } Type guard
fn stdout_limit_ok(v: usize) -> bool {
(1_048_576..=67_108_864).contains(&v)
} Prevention
- Derive config values from the same constants, not magic numbers
- Omit the key to take the 4 MiB default
- Remember the floor exists so one max-size ACP frame always fits
When it happens
Trigger: Setting a sub-MiB limit (e.g. 65536 or 0) to 'save memory'; passing usize::MAX trying to disable the cap; confusing KiB and MiB units.
Common situations: Operators copying a bytes-looking number without unit math; attempts to disable limits on huge tool outputs; config generated from a different constant set.
Related errors
- 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
- grok_cli env_passthrough entry `{name}` is invalid; expected
- grok_cli env_passthrough entry `{name}` is provider-owned (`
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/22c3a0a93cb095b7.
Report an issue: GitHub.