FuelLabs/sway · error · anyhow::Error

{:?}: could not read: {:?}

Error message

{:?}: could not read: {:?}

What it means

forc addr2line's exec does fs::read(command.sourcemap_path) and on any io failure returns "<path>: could not read: <io error debug>". Unlike most errors here it preserves the underlying error (kind, message) in {:?} form, so NotFound vs PermissionDenied is visible in the output.

Source

Thrown at forc/src/cli/commands/addr2line.rs:34

#[derive(Debug, Parser)]
pub(crate) struct Command {
    /// Where to search for the project root
    #[clap(short = 'S', long, default_value = ".")]
    pub search_dir: PathBuf,
    /// Source file mapping in JSON format
    #[clap(short = 'g', long)]
    pub sourcemap_path: PathBuf,
    /// How many lines of context to show
    #[clap(short, long, default_value = "2")]
    pub context: usize,
    /// Opcode index
    #[clap(short = 'i', long)]
    pub opcode_index: usize,
}

pub(crate) fn exec(command: Command) -> ForcResult<()> {
    let contents = fs::read(&command.sourcemap_path)
        .map_err(|err| anyhow!("{:?}: could not read: {:?}", command.sourcemap_path, err))?;

    let sm: SourceMap = serde_json::from_slice(&contents).map_err(|err| {
        anyhow!(
            "{:?}: invalid source map json: {}",
            command.sourcemap_path,
            err
        )
    })?;

    if let Some((mut path, range)) = sm.addr_to_span(command.opcode_index) {
        if path.is_relative() {
            path = command.search_dir.join(path);
        }

        let rr = read_range(&path, range, command.context)
            .map_err(|err| anyhow!("{:?}: could not read: {:?}", path, err))?;

        let path_str = format!("{path:?}");

View on GitHub (pinned to 47e5e902fa)

Solutions

  1. Regenerate the sourcemap: `forc build -g` (emits Forc.toml-adjacent sourcemap json for the binary) and pass that path with -g/--sourcemap-path
  2. Check the io error kind in the message: NotFound means wrong path, PermissionDenied means file mode problems
  3. Use an absolute path or run from the project root

Example fix

# before
forc addr2line -g missing-map.json -i 42

# after
forc build -g && forc addr2line -g out/debug/my_pkg.bin.json -i 42
Defensive patterns

Strategy: validation

Validate before calling

if !command.sourcemap_path.is_file() {
    anyhow::bail!(
        "sourcemap '{}' not found — build with `forc build -g` to generate it",
        command.sourcemap_path.display()
    );
}

Try / catch

let contents = match std::fs::read(&sm_path) {
    Ok(c) => c,
    Err(e) => anyhow::bail!("cannot read sourcemap {}: {e} — regenerate with `forc build -g`", sm_path.display()),
};

Prevention

When it happens

Trigger: `forc addr2line -g <sourcemap.json> -i <pc>` where the sourcemap path does not exist, is unreadable, or the relative path does not resolve from the current working directory.

Common situations: Forgetting that the sourcemap is only emitted when building with the sourcemap flag, stale paths after clean/rename, or running addr2line from a different directory than assumed.

Related errors


AI-assisted analysis of FuelLabs/sway@47e5e902fa (2026-08-16). Data as JSON: /api/errors/9968be03b9a3c738. Report an issue: GitHub.