warpdotdev/warp · error · anyhow::Error

Failed to read attachment file '{}': {e}

Error message

Failed to read attachment file '{}': {e}

What it means

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.

Source

Thrown at app/src/ai/agent_sdk/driver/attachments.rs:284

        Ok(())
    }

    with_bounded_retry(&operation, || async {
        attempt(http_client, download_url, file_path).await
    })
    .await
}

/// Process a file attachment for ambient agent upload.
/// Returns AttachmentInput with base64-encoded data.
/// All file types share the same 10MB size limit.
pub fn process_attachment(
    attachment_path: &PathBuf,
    index: usize,
) -> anyhow::Result<AttachmentInput> {
    let file_bytes = std::fs::read(attachment_path).map_err(|e| {
        anyhow::anyhow!(
            "Failed to read attachment file '{}': {e}",
            attachment_path.display()
        )
    })?;

    // Detect MIME type from file data using infer crate, fall back to file extension
    let mime_type = if file_bytes.len() >= MIN_IMAGE_HEADER_SIZE {
        infer::get(&file_bytes).map(|kind| kind.mime_type().to_string())
    } else {
        None
    };

    // If infer couldn't detect, fall back to file extension
    let mime_type = mime_type.unwrap_or_else(|| {
        from_path(attachment_path)
            .first_or_octet_stream()
            .to_string()
    });

View on GitHub (pinned to e72fd7aacb)

Solutions

  1. Verify the path exists and is a regular file: ls -l <path> / file <path>.
  2. Use an absolute path for the attachment argument, since the agent may resolve relative paths against a different working directory.
  3. Fix permissions (chmod +r) or re-mount the share if the IO error indicates access issues.
  4. Check the {e} suffix — it distinguishes NotFound (wrong path) from PermissionDenied (access) from IsADirectory (trailing slash / wrong target).

Example fix

// before
process_attachment(&PathBuf::from("report.pdf"), 0)?;

// after (pre-check and absolutize)
let path = std::path::absolute("report.pdf")?;
let meta = std::fs::metadata(&path)?;
anyhow::ensure!(meta.is_file(), "attachment is not a regular file");
process_attachment(&path, 0)?;
Defensive patterns

Strategy: validation

Validate before calling

let abs = std::path::absolute(attachment_path)?;
let meta = std::fs::metadata(&abs)?;
anyhow::ensure!(meta.is_file(), "attachment '{}' is not a regular file", abs.display());

Type guard

fn is_readable_file(p: &std::path::Path) -> bool {
    p.is_file() && std::fs::File::open(p).is_ok()
}

Try / catch

match process_attachment(&path, index) {
    Err(err) if err.to_string().contains("Failed to read attachment file") => {
        eprintln!("could not read '{}': check path/permissions", path.display());
        continue; // skip this attachment, keep processing others
    }
    rest => rest,
}

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Related errors


AI-assisted analysis of warpdotdev/warp@e72fd7aacb (2026-08-16). Data as JSON: /api/errors/8d7ca16becf7eb98. Report an issue: GitHub.