nushell/nushell · info

invalid xml document

Error message

invalid xml document

What it means

The 'invalid xml document' expect in query xml: the code first checks `if let Err(err) = package` and returns a labeled 'Invalid XML document' error for any parse failure, then calls package.expect("invalid xml document") on the value that just passed that check. The expect is therefore dead/unreachable — by the time it runs, the Result is guaranteed Ok. Users never see this panic; malformed XML input produces the proper labeled error with the parser message instead.

Source

Thrown at crates/nu_plugin_query/src/query_xml.rs:139

            return Err(
                LabeledError::new("problem with input data").with_label("query missing", call.head)
            );
        }
    };

    let node_output_options = NodeOutputOptions::from_call(call);

    let xpath = build_xpath(query_string, span)?;
    let input_string = input.coerce_str()?;
    let package = parser::parse(&input_string);

    if let Err(err) = package {
        return Err(
            LabeledError::new("Invalid XML document").with_label(err.to_string(), input.span())
        );
    }

    let package = package.expect("invalid xml document");

    let document = package.as_document();
    let mut context = Context::new();

    let mut namespaces = namespaces.unwrap_or_default();

    if namespaces.get("xml").is_none() {
        // XML namespace is always present, so we add it explicitly
        // it's used in attributes like `xml:lang`, `xml:base`, etc.
        namespaces.insert(
            "xml",
            Value::string("http://www.w3.org/XML/1998/namespace", call.head),
        );
    }

    // NB: `xmlns:whatever=` or `xmlns=` may look like an attribute, but XPath doesn't treat it as such.
    // Those are namespaces, and they are available through a separate axis (`namespace::`)
    // Thus we don't need to register a namespace for `xmlns` prefix

View on GitHub (pinned to 8e03210652)

Solutions

  1. No fix needed for users; malformed XML already yields a labeled 'Invalid XML document' error
  2. Maintainer cleanup: bind the success value in the check (`let package = parser::parse(&input_string).map_err(...)?.as_document()` style) to remove the unreachable expect
  3. Keep the error return before the unwrap when refactoring

Example fix

// before
let package = parser::parse(&input_string);
if let Err(err) = package {
    return Err(LabeledError::new("Invalid XML document").with_label(err.to_string(), input.span()));
}
let package = package.expect("invalid xml document");

// after: no unreachable expect
let package = parser::parse(&input_string).map_err(|err| {
    LabeledError::new("Invalid XML document").with_label(err.to_string(), input.span())
})?;
Defensive patterns

Strategy: try-catch

Validate before calling

// users cannot reach this panic; to fail gracefully on bad input the command already:
// 1) parses the XML, 2) returns LabeledError "Invalid XML document" on failure.
// You can pre-validate before invoking:
let looks_like_xml = input_str.trim_start().starts_with('<');

Type guard

fn is_parseable_xml(s: &str) -> bool {
    roxmltree::Document::parse(s).is_ok() // independent pre-check
}

Try / catch

// in plugin command run(): the error is already a labeled error, so just bubble it up
match execute_xpath(...) {
    Ok(v) => Ok(v),
    Err(e) => Err(e), // LabeledError carries "Invalid XML document" + parser detail
}

Prevention

When it happens

Trigger: None for the panic itself: any malformed XML input (unbalanced tags, bad encoding, wrong root structure) exits at the earlier `if let Err` block with LabeledError 'Invalid XML document'. The expect could only fire if the early-return check were removed or reordered.

Common situations: Running 'query xml' with a --query XPath against non-XML input — you get the graceful labeled error, not this panic. Relevant only to maintainers refactoring query_xml.rs who might break the check-then-expect ordering.

Related errors


AI-assisted analysis of nushell/nushell@8e03210652 (2026-08-17). Data as JSON: /api/errors/048365114a467894. Report an issue: GitHub.