hatoo/oha · error · anyhow::Error

Invalid form format: missing '=' in

Error message

Invalid form format: missing '=' in '{}'

What it means

Validation guard in FormPart::from_str (which parses curl's -F argument syntax). It fires when the -F string contains no '=' at all, so the part cannot be split into a name and a value/options section — e.g. '-F value_without_name'. Any -F argument missing the required name=value separator triggers it.

Solutions

  1. Rewrite the -F argument as name=value, e.g. '-F name=content' or '-F file=@path/to/file'.
  2. If passing a bare filename, prefix it with a field name: '-F upload=@filename'.
  3. Check shell quoting so '=' is not consumed or split by the shell before reaching the parser.
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at src/curl_compat.rs:103 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/941dc8452ca3e96f. Report an issue: GitHub.

Appendix: source

Thrown at src/curl_compat.rs:103

        format!("----formdata-oha-{hex_string}")
    }
}

impl FromStr for FormPart {
    type Err = anyhow::Error;

    /// Parse curl's -F format string
    /// Supports formats like:
    /// - `name=value`
    /// - `name=@filename` (file upload with filename)
    /// - `name=<filename` (file upload without filename)
    /// - `name=@filename;type=content-type`
    /// - `name=value;filename=name`
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        // Split on first '=' to separate name from value/options
        let (name, rest) = s
            .split_once('=')
            .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))?;

View on GitHub (pinned to 4efba2d113)