{"record":{"id":"8d7ca16becf7eb98","repo":"warpdotdev/warp","slug":"failed-to-read-attachment-file-e","errorCode":null,"errorMessage":"Failed to read attachment file '{}': {e}","messagePattern":"Failed to read attachment file '(.+?)': (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"app/src/ai/agent_sdk/driver/attachments.rs","lineNumber":284,"sourceCode":"\n        Ok(())\n    }\n\n    with_bounded_retry(&operation, || async {\n        attempt(http_client, download_url, file_path).await\n    })\n    .await\n}\n\n/// Process a file attachment for ambient agent upload.\n/// Returns AttachmentInput with base64-encoded data.\n/// All file types share the same 10MB size limit.\npub fn process_attachment(\n    attachment_path: &PathBuf,\n    index: usize,\n) -> anyhow::Result<AttachmentInput> {\n    let file_bytes = std::fs::read(attachment_path).map_err(|e| {\n        anyhow::anyhow!(\n            \"Failed to read attachment file '{}': {e}\",\n            attachment_path.display()\n        )\n    })?;\n\n    // Detect MIME type from file data using infer crate, fall back to file extension\n    let mime_type = if file_bytes.len() >= MIN_IMAGE_HEADER_SIZE {\n        infer::get(&file_bytes).map(|kind| kind.mime_type().to_string())\n    } else {\n        None\n    };\n\n    // If infer couldn't detect, fall back to file extension\n    let mime_type = mime_type.unwrap_or_else(|| {\n        from_path(attachment_path)\n            .first_or_octet_stream()\n            .to_string()\n    });","sourceCodeStart":266,"sourceCodeEnd":302,"githubUrl":"https://github.com/warpdotdev/warp/blob/e72fd7aacbbb2236d9b3be2aad7e7178fe94b4bc/app/src/ai/agent_sdk/driver/attachments.rs#L266-L302","documentation":"Wraps a std::fs::read failure while loading a file attachment for ambient-agent upload (process_attachment). The underlying {e} is the io::Error: NotFound, PermissionDenied, IsADirectory, etc. The path is included via attachment_path.display(), so the message names exactly which file could not be read.","triggerScenarios":"Calling process_attachment(&path, index) with a path that does not exist, is a directory, lacks read permission, or hit an OS-level IO error (file on an unmounted share, removed between listing and reading, path with invalid UTF-8 handled by the OS).","commonSituations":"Passing a relative path while the agent's cwd differs from the user's shell; a symlink pointing to a deleted target; attachments on network mounts that dropped; file permissions changed after the user listed it; typo in the attachment argument.","solutions":["Verify the path exists and is a regular file: ls -l <path> / file <path>.","Use an absolute path for the attachment argument, since the agent may resolve relative paths against a different working directory.","Fix permissions (chmod +r) or re-mount the share if the IO error indicates access issues.","Check the {e} suffix — it distinguishes NotFound (wrong path) from PermissionDenied (access) from IsADirectory (trailing slash / wrong target)."],"exampleFix":"// before\nprocess_attachment(&PathBuf::from(\"report.pdf\"), 0)?;\n\n// after (pre-check and absolutize)\nlet path = std::path::absolute(\"report.pdf\")?;\nlet meta = std::fs::metadata(&path)?;\nanyhow::ensure!(meta.is_file(), \"attachment is not a regular file\");\nprocess_attachment(&path, 0)?;","handlingStrategy":"validation","validationCode":"let abs = std::path::absolute(attachment_path)?;\nlet meta = std::fs::metadata(&abs)?;\nanyhow::ensure!(meta.is_file(), \"attachment '{}' is not a regular file\", abs.display());","typeGuard":"fn is_readable_file(p: &std::path::Path) -> bool {\n    p.is_file() && std::fs::File::open(p).is_ok()\n}","tryCatchPattern":"match process_attachment(&path, index) {\n    Err(err) if err.to_string().contains(\"Failed to read attachment file\") => {\n        eprintln!(\"could not read '{}': check path/permissions\", path.display());\n        continue; // skip this attachment, keep processing others\n    }\n    rest => rest,\n}","preventionTips":["Always pass absolute attachment paths — the agent's cwd may differ from your shell's.","Pre-check existence and read permission before invoking the upload flow.","Read the io::Error suffix to distinguish wrong path vs permissions vs directory."],"tags":["filesystem","attachments","io","rust"],"backgroundTag":null,"analyzedSha":"e72fd7aacbbb2236d9b3be2aad7e7178fe94b4bc","analyzedAt":"2026-08-16T08:27:25.381Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}