BigPizzaV3/CodexPlusPlus · error
File grew beyond the size limit
Error message
File grew beyond the size limit
What it means
This is the race-closing check in read_regular: even though the metadata size was within the limit, the file is re-read with file.take(limit + 1), and the actual byte count is verified to be at most limit. It throws when the file was modified (grew) between the metadata query and the read — i.e. a concurrent writer changed the file during the read, so the previously validated size snapshot is stale.
Solutions
- Close the running Codex/browser runtime processes, then retry the operation.
- Ensure only one instance of the manager/library operates on the installation at a time (the library already holds parent pins, but concurrent writers defeat any read).
- Retry the read — a transient race typically succeeds once the concurrent writer stops.
- If the file is persistently larger than the limit now, restore the original file from a clean installation (see 'Unexpected file type or size').
Example fix
// before: patching while the runtime is live Start-Process codex; cargo run -- prepare // after: stop the runtime first, then patch Stop-Process -Name codex -ErrorAction SilentlyContinue; cargo run -- prepare
Defensive patterns
Strategy: retry
Validate before calling
fn size_within(path: &Path, limit: u64) -> bool {
std::fs::metadata(path).map(|m| m.is_file() && m.len() <= limit).unwrap_or(false)
}
// check immediately before the read, and again on retry:
// assert!(size_within(path, 32 * 1024 * 1024)); Type guard
fn stable_size(path: &Path, limit: u64, checks: usize, gap: std::time::Duration) -> bool {
(0..checks).all(|_| {
let ok = size_within(path, limit);
std::thread::sleep(gap);
ok
})
} Try / catch
for attempt in 0..3 {
match read_operation() {
Err(e) if e.to_string().contains("grew beyond the size limit") && attempt < 2 => {
eprintln!("Concurrent writer detected; retrying after pause");
std::thread::sleep(std::time::Duration::from_millis(500));
}
Err(e) => return Err(e.into()),
Ok(v) => { use_value(v); break; }
}
} Prevention
- Stop the Codex CLI / browser runtime processes before preparing or restoring files
- Run only one instance of the manager against a given installation at a time
- Schedule patching outside of update windows when an updater may be writing files
- If reads keep racing, check for active writers with Resource Monitor / handle.exe on the file
When it happens
Trigger: A concurrent process (Codex updater, the browser runtime itself, another library instance, antivirus quarantine/restore) appends to or rewrites the target file while read_regular is in progress, so the bytes read exceed the limit even though metadata said it fit.
Common situations: Running prepare/patching while the Codex CLI or its browser runtime is actively running and rewriting files; two instances of the manager operating on the same installation concurrently; an update job racing a status read.
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
- Concurrent adapter upgrade
- Concurrent recovery change
- Concurrent runtime change
- Recovery verification failed
- Unexpected file type or size
AI-assisted analysis of BigPizzaV3/CodexPlusPlus@b1ed92e5e4 (2026-09-19).
Data as JSON: /api/errors/aaf2842a4b3a0efd.
Report an issue: GitHub.
Appendix: source
Thrown at crates/codex-plus-core/src/native_browser.rs:191
options.share_mode(0x1).custom_flags(0x00200000);
}
let file = options.open(path)?;
let meta = file.metadata()?;
#[cfg(windows)]
{
use std::os::windows::fs::MetadataExt;
ensure!(
meta.file_attributes() & 0x400 == 0,
"File is a reparse point"
);
}
ensure!(
meta.is_file() && meta.len() <= limit,
"Unexpected file type or size"
);
let mut bytes = Vec::new();
file.take(limit + 1).read_to_end(&mut bytes)?;
ensure!(
bytes.len() as u64 <= limit,
"File grew beyond the size limit"
);
Ok(bytes)
}
fn write_new(path: &Path, bytes: &[u8]) -> Result<File> {
let _guards = pin_parents(path)?;
let mut file = OpenOptions::new().write(true).create_new(true).open(path)?;
file.write_all(bytes)?;
file.sync_all()?;
Ok(file)
}
fn atomic_write(path: &Path, bytes: &[u8]) -> Result<()> {
atomic_write_with_modified(path, bytes, None)
}
View on GitHub (pinned to b1ed92e5e4)