Hmbown/CodeWhale · error · std::io::Error
config file exceeds the 1 MiB limit
Error message
config file {} exceeds the 1 MiB limit What it means
The config loader reads config files with a hard cap of MAX_CONFIG_FILE_BYTES (1 MiB), using read(2) with O_NOFOLLOW and take(limit+1) so oversized files are detected without reading them fully into memory unbounded. If the file's byte length exceeds 1 MiB it returns an InvalidData io::Error naming the path. This is a safety guard against absurd/corrupt config files and symlink attacks.
Solutions
- Inspect the file at the reported path (`ls -lh`, `wc -c`) and trim it under 1 MiB — remove duplicated or commented-out sections
- Regenerate the config from a known-good template instead of hand-editing the bloated one
- Check whether scripts/CI write into the config path and bound their output
- Verify the path is a regular file, not a symlink to something huge
Defensive patterns
Strategy: validation
Validate before calling
import os
path = "~/.codewhale/config.toml"
if os.path.getsize(os.path.expanduser(path)) > 1024*1024:
raise SystemExit(f"{path} exceeds 1 MiB; trim before loading") Try / catch
match std::fs::read(path) {
Err(e) if e.kind() == std::io::ErrorKind::InvalidData =>
eprintln!("config too large (>1MiB): regenerate it"),
other => other,
} Prevention
- Keep machine-generated data out of the config file; reference external files instead
- Lint configs in CI for size before deployment
- Alert if the config path grows beyond a few hundred KiB
- Ensure the path resolves to a regular file, not a symlink
When it happens
Trigger: Loading a config file (via the no-follow hardened reader path) whose size on disk is greater than 1 MiB — the read is capped at MAX_CONFIG_FILE_BYTES + 1 bytes and the length check fires.
Common situations: A config generator or tool concatenated credentials/prompts into the config until it grew past 1 MiB; a symlink or bind-mount pointed the config path at a huge file (the O_NOFOLLOW flag catches plain symlinks); accidental binary/log file placed at the config path.
Understand the failure class
Background: "File too large" / "file size exceeds limit" errors: why libraries cap file sizes and how to fix them — this error's family across 46 libraries.
Related errors
- bundle at is bytes; the limit is bytes
- agent profile provider cannot be empty
- agent profile provider must be a simple provider id
- api_key cannot be empty string
- approval_policy ' ' is not allowed by requirements ( )
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/c8b27a2f86a376bf.
Report an issue: GitHub.
Appendix: source
Thrown at crates/config/src/lib.rs:6880
read_string_no_follow(&path)
.with_context(|| format!("failed to read {label} at {}", path.display()))
}
/// Maximum bytes read from a config file. Configs are kilobytes; anything
/// larger is not a config file.
const MAX_CONFIG_FILE_BYTES: u64 = 1024 * 1024;
#[cfg(unix)]
fn read_string_no_follow(path: &Path) -> std::io::Result<String> {
let file = fs::OpenOptions::new()
.read(true)
.custom_flags(libc::O_NOFOLLOW)
.open(path)?;
let mut raw = String::new();
file.take(MAX_CONFIG_FILE_BYTES + 1)
.read_to_string(&mut raw)?;
if raw.len() as u64 > MAX_CONFIG_FILE_BYTES {
return Err(std::io::Error::new(
std::io::ErrorKind::InvalidData,
format!("config file {} exceeds the 1 MiB limit", path.display()),
));
}
Ok(raw)
}
#[cfg(not(unix))]
fn read_string_no_follow(path: &Path) -> std::io::Result<String> {
let file = fs::File::open(path)?;
let mut raw = String::new();
file.take(MAX_CONFIG_FILE_BYTES + 1)
.read_to_string(&mut raw)?;
if raw.len() as u64 > MAX_CONFIG_FILE_BYTES {
return Err(std::io::Error::new(
std::io::ErrorKind::InvalidData,
format!("config file {} exceeds the 1 MiB limit", path.display()),
));View on GitHub (pinned to 73e0f67d83)