hatoo/oha · error · anyhow::Error

Failed to read file

Error message

Failed to read file '{}': {}

What it means

I/O failure raised by FormPart::from_str when the -F value uses the '@filename' or '<filename' file-upload form but the file cannot be opened and read (file does not exist, insufficient permissions, or it is a directory). The '{}' placeholders carry the path and the underlying io::Error.

Solutions

  1. Verify the path is correct and the file exists (ls / realpath).
  2. Check read permissions on the file and on every directory in its path.
  3. Ensure the target is a regular file, not a directory or special device.
  4. If the path may be relative, confirm the process's current working directory.
Defensive patterns

Strategy: fallback

When it happens

Trigger: Thrown at src/curl_compat.rs:121 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of hatoo/oha@4efba2d113 (2026-09-09). Data as JSON: /api/errors/8d2cf5cef587c607. Report an issue: GitHub.

Appendix: source

Thrown at src/curl_compat.rs:121

            .ok_or_else(|| anyhow::anyhow!("Invalid form format: missing '=' in '{}'", s))?;

        let name = name.to_string();

        // Parse the value part which may contain semicolon-separated options
        let parts: Vec<&str> = rest.split(';').collect();
        let value_part = parts[0];

        let mut filename = None;
        let mut content_type = None;
        let data;

        // Check if this is a file upload (@filename or <filename)
        if let Some(file_path) = value_part.strip_prefix('@') {
            // Remove '@' prefix

            // Read file content
            data = std::fs::read(file_path)
                .map_err(|e| anyhow::anyhow!("Failed to read file '{}': {}", file_path, e))?;

            // Extract filename from path
            filename = std::path::Path::new(file_path)
                .file_name()
                .and_then(|name| name.to_str())
                .map(|s| s.to_string());
        } else if let Some(file_path) = value_part.strip_prefix('<') {
            // Remove '<' prefix

            // Read file content
            data = std::fs::read(file_path)
                .map_err(|e| anyhow::anyhow!("Failed to read file '{}': {}", file_path, e))?;

            // Do not set filename for '<' format (curl behavior)
        } else {
            // Regular form field with string value
            data = value_part.as_bytes().to_vec();
        }

View on GitHub (pinned to 4efba2d113)