{"record":{"id":"9968be03b9a3c738","repo":"FuelLabs/sway","slug":"could-not-read","errorCode":null,"errorMessage":"{:?}: could not read: {:?}","messagePattern":"(.+?): could not read: (.+?)","errorType":"console","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"forc/src/cli/commands/addr2line.rs","lineNumber":34,"sourceCode":"#[derive(Debug, Parser)]\npub(crate) struct Command {\n    /// Where to search for the project root\n    #[clap(short = 'S', long, default_value = \".\")]\n    pub search_dir: PathBuf,\n    /// Source file mapping in JSON format\n    #[clap(short = 'g', long)]\n    pub sourcemap_path: PathBuf,\n    /// How many lines of context to show\n    #[clap(short, long, default_value = \"2\")]\n    pub context: usize,\n    /// Opcode index\n    #[clap(short = 'i', long)]\n    pub opcode_index: usize,\n}\n\npub(crate) fn exec(command: Command) -> ForcResult<()> {\n    let contents = fs::read(&command.sourcemap_path)\n        .map_err(|err| anyhow!(\"{:?}: could not read: {:?}\", command.sourcemap_path, err))?;\n\n    let sm: SourceMap = serde_json::from_slice(&contents).map_err(|err| {\n        anyhow!(\n            \"{:?}: invalid source map json: {}\",\n            command.sourcemap_path,\n            err\n        )\n    })?;\n\n    if let Some((mut path, range)) = sm.addr_to_span(command.opcode_index) {\n        if path.is_relative() {\n            path = command.search_dir.join(path);\n        }\n\n        let rr = read_range(&path, range, command.context)\n            .map_err(|err| anyhow!(\"{:?}: could not read: {:?}\", path, err))?;\n\n        let path_str = format!(\"{path:?}\");","sourceCodeStart":16,"sourceCodeEnd":52,"githubUrl":"https://github.com/FuelLabs/sway/blob/47e5e902faa42baf652dd6a0c88cd23390c1a614/forc/src/cli/commands/addr2line.rs#L16-L52","documentation":"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.","triggerScenarios":"`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.","commonSituations":"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.","solutions":["Regenerate the sourcemap: `forc build -g` (emits Forc.toml-adjacent sourcemap json for the binary) and pass that path with -g/--sourcemap-path","Check the io error kind in the message: NotFound means wrong path, PermissionDenied means file mode problems","Use an absolute path or run from the project root"],"exampleFix":"# before\nforc addr2line -g missing-map.json -i 42\n\n# after\nforc build -g && forc addr2line -g out/debug/my_pkg.bin.json -i 42","handlingStrategy":"validation","validationCode":"if !command.sourcemap_path.is_file() {\n    anyhow::bail!(\n        \"sourcemap '{}' not found — build with `forc build -g` to generate it\",\n        command.sourcemap_path.display()\n    );\n}","typeGuard":null,"tryCatchPattern":"let contents = match std::fs::read(&sm_path) {\n    Ok(c) => c,\n    Err(e) => anyhow::bail!(\"cannot read sourcemap {}: {e} — regenerate with `forc build -g`\", sm_path.display()),\n};","preventionTips":["Make `forc build -g` a prerequisite step in any addr2line workflow","Pass absolute sourcemap paths, especially in CI"],"tags":["forc","addr2line","sourcemap","file-not-found"],"backgroundTag":null,"analyzedSha":"47e5e902faa42baf652dd6a0c88cd23390c1a614","analyzedAt":"2026-08-16T07:57:45.555Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}