linera-io/linera-protocol · error · std::io::Error
{}: {error}
Error message
{}: {error} What it means
Bytecode::load_from_file reads the raw bytes of a Wasm module from disk to build a Bytecode value, which linera-client later uses to publish a module to a chain. Any tokio::fs::read failure is re-wrapped into a new std::io::Error that keeps the original ErrorKind but prepends the failing path. You only see this error when the file at the given path cannot be read at all; malformed Wasm content is not detected here.
Source
Thrown at linera-base/src/data_types.rs:1520
pub struct Bytecode {
/// Bytes of the bytecode.
#[serde(with = "serde_bytes")]
#[debug(with = "hex_debug")]
pub bytes: Vec<u8>,
}
impl Bytecode {
/// Creates a new [`Bytecode`] instance using the provided `bytes`.
pub fn new(bytes: Vec<u8>) -> Self {
Bytecode { bytes }
}
/// Loads bytecode from a Wasm module file.
#[cfg(not(target_arch = "wasm32"))]
pub async fn load_from_file(path: impl AsRef<std::path::Path>) -> std::io::Result<Self> {
let path = path.as_ref();
let bytes = tokio::fs::read(path).await.map_err(|error| {
std::io::Error::new(error.kind(), format!("{}: {error}", path.display()))
})?;
Ok(Bytecode { bytes })
}
/// Compresses the [`Bytecode`] into a [`CompressedBytecode`].
#[cfg(not(target_arch = "wasm32"))]
pub fn compress(&self) -> CompressedBytecode {
#[cfg(with_metrics)]
let _compression_latency = metrics::BYTECODE_COMPRESSION_LATENCY.measure_latency();
let compressed_bytes_vec = zstd::stream::encode_all(&*self.bytes, 19)
.expect("Compressing bytes in memory should not fail");
CompressedBytecode {
compressed_bytes: Arc::new(compressed_bytes_vec.into_boxed_slice()),
}
}
/// Compresses the [`Bytecode`] into a [`CompressedBytecode`].View on GitHub (pinned to 6c226ddcb3)
Solutions
- Verify the file exists at the exact path passed: `ls -l <path>`; if missing, build it first with `cargo build --target wasm32-unknown-unknown --release` (or the project's `linera build`) and copy the exact emitted path from the build output.
- If the file exists, check it is a regular file with read permission (`file <path>`, `chmod`/`chown` as needed) and that you are running the client from the directory the relative path assumes — or switch to an absolute path.
- If building for a different environment, confirm the wasm files were actually produced for wasm32-unknown-unknown (check `target/wasm32-unknown-unknown/release/`) and not overwritten by a native-only build.
- In code, pre-check with tokio::fs::metadata / try_exists before loading and fail with a message that includes the build command to run.
Example fix
// before
let bytecode = Bytecode::load_from_file(&path).await?; // io error may be path-less in logs upstream
// after
if !tokio::fs::try_exists(&path).await? {
anyhow::bail!(
"bytecode not found at {}: build it first with `cargo build --target wasm32-unknown-unknown --release`",
path.display()
);
}
let bytecode = Bytecode::load_from_file(&path).await?; Defensive patterns
Strategy: try-catch
Validate before calling
async fn bytecode_readable(path: &std::path::Path) -> std::io::Result<()> {
let meta = tokio::fs::metadata(path).await?;
if !meta.is_file() {
return Err(std::io::Error::new(
std::io::ErrorKind::InvalidInput,
format!("{} is not a regular file", path.display()),
));
}
Ok(())
} Try / catch
match Bytecode::load_from_file(&path).await {
Ok(bc) => bc,
Err(e) if e.kind() == std::io::ErrorKind::NotFound => {
return Err(anyhow::anyhow!(
"bytecode {} not found; build with `cargo build --target wasm32-unknown-unknown --release` first",
path.display()
));
}
Err(e) => return Err(e.into()),
} Prevention
- Always build the wasm32 artifacts before publish and pass the exact paths the build prints.
- Script the publish step to assert both artifact paths exist before invoking the client.
- Use absolute paths (or a fixed cwd) in CI so relative artifact paths never drift.
When it happens
Trigger: Calling Bytecode::load_from_file(path) (directly, or via ClientContext::publish_module with a --contract/--service path) where path does not exist, points to a directory, lacks read permission, or is unreachable (broken symlink, missing mount, wrong container volume). The error kind is NotFound, IsADirectory, PermissionDenied, etc., mirroring the underlying OS error.
Common situations: Running `linera publish-module` before building the Wasm artifacts, so target/wasm32-unknown-unknown/release/<app>_{contract,service}.wasm does not exist yet; passing a path from target/release (native build) instead of the wasm32 target dir; relative paths resolved from the wrong working directory; CI or Docker runs where the build output is not mounted into the container.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- failed to load contract bytecode from {contract:?}: {e}
- failed to load service bytecode from {service:?}: {e}
- BytecodeTooLarge
- failed to load data blob bytes from {blob_path:?}: {e}
- failed to read SNAP file {path:?}: {e}
AI-assisted analysis of linera-io/linera-protocol@6c226ddcb3 (2026-08-22).
Data as JSON: /api/errors/2a41c061d12b5723.
Report an issue: GitHub.