ducaale/xh · error

Request body (from a file) and request data (key=value)…

Error message

Request body (from a file) and request data (key=value) cannot be mixed.

What it means

A request body can come either from a file/stdin (`@file` or redirect syntax) or from key=value request items — never both, since there is only one body. `body_from_file` detects any `DataField`, `JsonField`, `DataFieldFromFile`, or `JsonFieldFromFile` item alongside the file body and returns this error to force the user to pick one source.

Solutions

  1. Remove the `key=value`/`key:=value` items if the file (or stdin) should be the whole body.
  2. Drop the `@file` body and express everything as request items if fields are what you want.
  3. Move non-body data to the correct syntax: query params use `key==value`, headers use `Header:value`.

Example fix

// before
xh POST :8080 @data.json name=John
// after
xh POST :8080 @data.json
Defensive patterns

Strategy: validation

Validate before calling

# guard: don't mix @file/stdin body with data items
if { echo "$args" | grep -qE '(^| )@'; } && echo "$args" | grep -qE '[A-Za-z0-9_]+(=|:=)'; then
  echo 'cannot mix file body with key=value items'; exit 1
fi

Try / catch

match result {
    Err(e) if e.to_string().contains("cannot be mixed") => {
        eprintln!("choose either a file body or request items, not both");
    }
    other => other?,
}

Prevention

When it happens

Trigger: Running `xh POST :8080 @data.json name=John` (file body plus `=`/`:=` items), or `cat body.json | xh POST :8080 key=value` — stdin body combined with data items.

Common situations: Appending query/auth-looking items that should have been `==` (query params) or headers (`Header:value`) but were typed as body fields; scripting where a body file and generated fields are both present.

Understand the failure class

Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.

Related errors


AI-assisted analysis of ducaale/xh@2404aceecc (2026-09-13). Data as JSON: /api/errors/133ff5fe02b3f382. Report an issue: GitHub.

Appendix: source

Thrown at src/request_items.rs:417

    fn body_from_file(self) -> Result<Body> {
        let mut body = None;
        if self
            .items
            .iter()
            .any(|item| matches!(item, RequestItem::FormFile {key, ..} if !key.is_empty()))
        {
            return Err(anyhow!(
                "Can't use file fields in JSON mode (perhaps you meant --form?)"
            ));
        }
        for item in self.items {
            match item {
                RequestItem::DataField { .. }
                | RequestItem::JsonField(..)
                | RequestItem::DataFieldFromFile { .. }
                | RequestItem::JsonFieldFromFile(..) => {
                    return Err(anyhow!(
                        "Request body (from a file) and request data (key=value) cannot be mixed."
                    ));
                }
                RequestItem::FormFile {
                    key,
                    file_name,
                    file_type,
                    file_name_header,
                } => {
                    assert!(key.is_empty());
                    if body.is_some() {
                        return Err(anyhow!("Can't read request from multiple files"));
                    }
                    body = Some(Body::File {
                        file_type: file_type
                            .as_deref()
                            .or_else(|| mime_guess::from_path(&file_name).first_raw())
                            .map(HeaderValue::from_str)

View on GitHub (pinned to 2404aceecc)