Hmbown/CodeWhale · error · anyhow::Error
private lane environment {} exceeds {} bytes
Error message
private lane environment {} exceeds {} bytes What it means
Raised by read_lane_environment when the private lane environment file (a JSON array of key/value pairs the parent pinned for the lane) stats larger than MAX_ENVIRONMENT_BYTES (1 MiB, runtime.rs:174). The guard prevents a corrupt, foreign, or hostile file from being read wholesale into memory. This is the first of two checks: a stat-based pre-check before fs::read.
Source
Thrown at crates/lane/src/runtime.rs:342
reader.consume(take);
if ended_line {
break;
}
}
if line.is_empty() && reached_eof {
return Ok(());
}
append_child_output(&log_path, stream, &line)?;
if reached_eof {
return Ok(());
}
}
}
fn read_lane_environment(path: &Path) -> Result<Vec<(String, String)>> {
let metadata = fs::metadata(path).with_context(|| format!("stat {}", path.display()))?;
if metadata.len() > MAX_ENVIRONMENT_BYTES {
bail!(
"private lane environment {} exceeds {} bytes",
path.display(),
MAX_ENVIRONMENT_BYTES
);
}
let bytes = fs::read(path).with_context(|| format!("read {}", path.display()))?;
if bytes.len() as u64 > MAX_ENVIRONMENT_BYTES {
bail!(
"private lane environment {} exceeds {} bytes",
path.display(),
MAX_ENVIRONMENT_BYTES
);
}
let environment: Vec<(String, String)> =
serde_json::from_slice(&bytes).with_context(|| format!("parse {}", path.display()))?;
for (key, _) in &environment {
if !valid_environment_key(key) {
bail!("invalid lane environment key {key:?}");View on GitHub (pinned to 0c42157ee5)
Solutions
- Shrink the environment to essential keys and re-start the lane
- Inspect the file named in the message (ls -l / stat) and delete it if it is stale, then retry the start
- Move large values out of the environment and pass them via a file path or command argument
- If you control the writer, keep the serialized environment under 1 MiB before the lane is launched so both guards stay green
Example fix
// before
let spec = LaneStartSpec {
command: vec!["bash".into()],
environment: all_exports.clone(), // may exceed 1 MiB
..
};
// after
let environment: Vec<(String, String)> = all_exports
.into_iter()
.filter(|(k, _)| matches!(k.as_str(), "PATH" | "HOME" | "CODEWHALE_*"))
.collect();
assert!(serde_json::to_vec(&environment).unwrap().len() <= 1024 * 1024);
let spec = LaneStartSpec { command: vec!["bash".into()], environment, .. }; Defensive patterns
Strategy: validation
Validate before calling
const MAX_ENVIRONMENT_BYTES: usize = 1024 * 1024;
fn environment_within_bound(environment: &[(String, String)]) -> bool {
serde_json::to_vec(environment)
.map(|bytes| bytes.len() <= MAX_ENVIRONMENT_BYTES)
.unwrap_or(false)
}
// before start:
assert!(environment_within_bound(&spec.environment), "environment too large"); Prevention
- Serialize and size-check the environment before every lane start
- Keep secrets and payloads out of the lane environment; pass file paths instead
- Use fresh log/state directories per lane generation so stale oversized files cannot be inherited
When it happens
Trigger: Calling a lane start that leads to read_lane_environment(path) where fs::metadata(path).len() > 1_048_576. Concretely: LaneStartSpec environment serialized by write_lane_environment exceeded 1 MiB, or the environment path points at a stale/unrelated large file in a reused log directory.
Common situations: Passing bulky values (base64 blobs, long tokens, serialized payloads) through the lane environment; a log directory reused across lane generations so an old environment file survives; external tooling writing into the lane's private state directory.
Related errors
- serialized lane exit receipt exceeds size bound
- lane exit receipt {} exceeds {} bytes
- parallel(): expected an array of thunks
- project workspace path cannot be empty
- project workspace path cannot contain '..' components
AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20).
Data as JSON: /api/errors/524c69f3c251a0ce.
Report an issue: GitHub.