ducaale/xh · error

Message signature components require both…

Error message

Message signature components require both --unstable-m-sig-id and --unstable-m-sig-key.

What it means

When message signature support is enabled, signing requires an identity: both a key ID (`--unstable-m-sig-id`) and key material (`--unstable-m-sig-key`). Supplying signature components without a complete key pair leaves the signer unable to construct a `SignatureSpec`, so `run` rejects the combination up front.

Solutions

  1. Provide both flags together: `--unstable-m-sig-id <id> --unstable-m-sig-key <key>`.
  2. Remove the signature component flags entirely if you did not intend to sign the request.
  3. Check that the key/id values are actually being passed (not empty env vars) in your script.

Example fix

// before
xh --unstable-m-sig-components="@authority" POST https://api.example.com
// after
xh --unstable-m-sig-id=my-key-id --unstable-m-sig-key=$SECRET --unstable-m-sig-components="@authority" POST https://api.example.com
Defensive patterns

Strategy: validation

Validate before calling

# shell guard before invoking xh:
if [[ -n "$M_SIG_COMPONENTS" && ( -z "$M_SIG_ID" || -z "$M_SIG_KEY" ) ]]; then
  echo 'm-sig components require both id and key'; exit 1
fi

Prevention

When it happens

Trigger: Passing signature component flags (e.g. `--unstable-m-sig-components`) with only one of `--unstable-m-sig-id` / `--unstable-m-sig-key`, or with neither, while the `http-message-signatures` feature is enabled (`has_components() && !has_key_pair()`).

Common situations: Partially copying example commands from documentation; env-var-driven config where one of the two values is unset; switching between shared-secret and key-based setups and dropping a flag.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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

Appendix: source

Thrown at src/main.rs:605

        for header in &headers_to_unset {
            request.headers_mut().remove(header);
        }

        #[cfg(not(feature = "http-message-signatures"))]
        if args.m_sig.m_sig_id.is_some()
            || args.m_sig.m_sig_key.is_some()
            || args.m_sig.m_sig_alg.is_some()
            || args.m_sig.has_components()
        {
            return Err(anyhow!(
                "This binary was built without message signature support. Enable the `http-message-signatures` feature."
            ));
        }

        #[cfg(feature = "http-message-signatures")]
        if args.m_sig.has_components() && !args.m_sig.has_key_pair() {
            return Err(anyhow!(
                "Message signature components require both --unstable-m-sig-id and --unstable-m-sig-key."
            ));
        }

        #[cfg(feature = "http-message-signatures")]
        if let Some((key_id, key_material)) = args.m_sig.key_pair() {
            let m_sig_components = args.m_sig.flattened_components();
            let m_sig_algorithm = args.m_sig.algorithm().map(Into::into);
            message_signature::sign_request(
                &mut request,
                key_id,
                key_material,
                (!m_sig_components.is_empty()).then_some(m_sig_components.as_slice()),
                m_sig_algorithm,
            )?;
        }

        request

View on GitHub (pinned to 2404aceecc)