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

  1. Regenerate the eszip/compiled binary from source with a current Deno version.
  2. Clear the affected cache (DENO_DIR, downloaded artifacts) and re-download fully.
  3. Add post-copy integrity checks (size + hash) in CI before an artifact is used.
  4. 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

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


AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20). Data as JSON: /api/errors/e9ef4bb485306417. Report an issue: GitHub.