denoland/deno · error
unexpected end of bytes
Error message
unexpected end of bytes
What it means
eszip v2 parser helper move_bytes: every length-prefixed field (u32 sizes, string bytes, package table entries) slices the input by declared length; if fewer bytes remain than the declared length requires, parsing stops with ErrorKind::UnexpectedEof and this message. It is the generic signature of a truncated eszip archive.
Source
Thrown at libs/eszip/v2.rs:1898
let (input, name) = move_bytes(input, size as usize)?;
let text = String::from_utf8(name.to_vec()).map_err(|_| {
std::io::Error::new(std::io::ErrorKind::InvalidData, "invalid utf-8 data")
})?;
Ok((input, text))
}
fn parse_u32(input: &[u8]) -> std::io::Result<(&[u8], u32)> {
let (input, value_bytes) = move_bytes(input, 4)?;
let value = u32::from_be_bytes(value_bytes.try_into().unwrap());
Ok((input, value))
}
fn move_bytes(
bytes: &[u8],
len: usize,
) -> Result<(&[u8], &[u8]), std::io::Error> {
if bytes.len() < len {
Err(std::io::Error::new(
std::io::ErrorKind::UnexpectedEof,
"unexpected end of bytes",
))
} else {
Ok((&bytes[len..], &bytes[..len]))
}
}
#[derive(Debug)]
struct Section(Vec<u8>, Options);
impl Section {
/// Reads a section that's defined as:
/// Size (4) | Body (n) | Hash (32)
async fn read<R: futures::io::AsyncRead + Unpin>(
mut reader: R,
options: Options,
) -> Result<Section, ParseError> {View on GitHub (pinned to 9ad36f7a2c)
Solutions
- Regenerate the eszip/compiled binary from source with a current Deno version.
- Clear the affected cache (DENO_DIR, downloaded artifacts) and re-download fully.
- Add post-copy integrity checks (size + hash) in CI before an artifact is used.
- Ensure the producing step completes (check exit codes, disk space) before publishing artifacts.
Example fix
# before scp -r artifacts/ host:/app/ # copy interrupted -> truncated eszip /app/binary run # unexpected end of bytes # after deno compile -o artifacts/app main.ts sha256sum artifacts/app > artifacts/app.sha256 # after transfer: sha256sum -c artifacts/app.sha256 && /app/artifacts/app
Defensive patterns
Strategy: fallback
Validate before calling
const expectedBytes = 1_234_567; // recorded at build time
const st = await stat(artifact);
if (st.size !== expectedBytes) throw new Error(`artifact truncated: ${st.size} != ${expectedBytes} bytes`); Try / catch
try { await run(); } catch (e) { if (/unexpected end of bytes/.test(String(e))) { await regenerateArtifact(); } else throw e; } Prevention
- Check exit codes and disk space in the step that produces eszips/compiled binaries.
- Write artifacts atomically (tmp file + rename) so partial writes never look complete.
- Verify artifact size/hash after copy/deploy steps, before first execution.
When it happens
Trigger: An eszip file cut short relative to its internal section lengths: interrupted `deno compile`, partial download/copy, cache file truncated by disk-full, or a producer version mismatch writing headers that promise more bytes than follow.
Common situations: CI caching partial artifacts; deploys interrupted mid-copy; disk quota hit while writing the npm cache; artifacts generated by an older/newer eszip version with incompatible layout.
Related errors
- invalid utf-8 data
- unexpected EOF while reading HTTP/1 body
- "bytesWritten" must be 0 when calling respond() on a closed
- "bytesWritten" must be greater than 0 when calling respond()
- The view's length must be greater than 0 when calling respon
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/e9ef4bb485306417.
Report an issue: GitHub.