Hmbown/CodeWhale · error
An existing Fleet artifact contains different bytes
Error message
An existing Fleet artifact contains different bytes
What it means
Fleet artifact publication is immutable: when the target file already exists, write re-opens it and compares the existing bytes with the new payload. If they differ, publication fails with this error instead of overwriting — an existing artifact is treated as an immutable published record. Identical re-publication is allowed and returns Ok.
Solutions
- Use a content-addressed or run-unique relative path so distinct payloads never collide.
- If the new bytes are the correct replacement, this immutability is intentional — remove the stale artifact deliberately and republish, or publish under a new versioned name.
- If the existing file was corrupted externally, restore it from the recorded digest/receipt or delete it and republish.
- Verify the payload is actually what you intend — the mismatch may reveal a non-deterministic generation step upstream.
Example fix
// before
artifacts::write(ws, Path::new("report.txt"), &new_bytes)?;
// after
let path = format!("report-{}.txt", sha256_hex(&new_bytes));
artifacts::write(ws, Path::new(&path), &new_bytes)?; Defensive patterns
Strategy: validation
Validate before calling
let path = format!("artifacts/{}-{}", run_id, file_name);
if ws.join(&path).exists() {
// treat as immutable: publish under a new name or compare first
} Try / catch
match artifacts::write(ws, &path, &bytes) {
Err(e) if e.to_string().contains("different bytes") => {
eprintln!("artifact {} already published with other content; use a new path", path);
}
r => r?,
} Prevention
- Make artifact paths content-addressed or run-scoped so re-publication never collides.
- Never manually edit files under the Fleet workspace.
- Treat existing artifacts as immutable records; version instead of overwrite.
When it happens
Trigger: Calling artifacts::write with a relative path that already exists in the Fleet workspace but whose on-disk content differs from the bytes being written (io::ErrorKind::AlreadyExists from publish, then byte comparison fails).
Common situations: Two runs writing different content to the same deterministic artifact path; a retry reusing a path after the payload changed (e.g. regenerated report with new data); manual editing or corruption of a previously published artifact; a stale artifact left from an earlier version of the pipeline.
Understand the failure class
Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.
Related errors
- immutable artifact handle already contains different bytes
- AlreadyExists
- Fleet artifact checksum does not match the recorded receipt
- Fleet artifact exceeds the 16 MiB limit
- Fleet artifact exceeds the 16 MiB verification limit
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/b678c5dd3ea006a7.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/fleet/artifacts.rs:36
// without retaining all bytes. The writer shares the ceiling so it cannot
// publish an artifact the evidence reader is unable to verify.
const MAX_ARTIFACT_BYTES: u64 = 16 * 1024 * 1024;
pub(crate) fn write(workspace: &Path, relative: &Path, bytes: &[u8]) -> Result<()> {
ensure!(
bytes.len() as u64 <= MAX_ARTIFACT_BYTES,
"Fleet artifact exceeds the 16 MiB limit"
);
let parent = WorkspaceFile::open(workspace, relative, true)?;
match parent.publish(bytes) {
Ok(()) => Ok(()),
Err(error) if error.kind() == io::ErrorKind::AlreadyExists => {
let existing = parent.open_file()?;
let mut saved = Vec::new();
existing
.take(bytes.len() as u64 + 1)
.read_to_end(&mut saved)?;
ensure!(
saved == bytes,
"An existing Fleet artifact contains different bytes"
);
Ok(())
}
Err(error) => Err(error).context("Publishing Fleet artifact"),
}
}
pub(crate) fn read_verified(
workspace: &Path,
artifact: &FleetArtifactRef,
preview_limit: u64,
) -> Result<(Vec<u8>, u64)> {
let parent = WorkspaceFile::open(workspace, &artifact.path, false)?;
let file = parent.open_file()?;
let size = file.metadata()?.len();
ensure!(View on GitHub (pinned to 73e0f67d83)