juspay/hyperswitch · error · ApiErrorResponse

Invalid Worldpayxml metadata format

Error message

Invalid Worldpayxml metadata format

What it means

This error is raised when configuring the Worldpayxml connector in Hyperswitch's unified connector service: the caller supplied a `metadata` JSON value, but `serde_json::from_value::<WorldpayxmlMetadata>` failed to deserialize it into the expected `WorldpayxmlMetadata` struct. The underlying serde error is discarded (`map_err(|_| ...)`) and replaced by this opaque message, so any shape mismatch — wrong types, unknown/misspelled fields with deny-unknown-fields, or a non-object value — surfaces as this error. It indicates the merchant_connector_account metadata for Worldpayxml is malformed, not that credentials are wrong.

Source

Thrown at crates/router/src/core/unified_connector_service/connector_config.rs:1572

                    api_secret,
                } => Ok(Self::Worldpay {
                    username: key1.clone(),
                    password: api_key.clone(),
                    entity_id: api_secret.clone(),
                    merchant_name: None,
                }),
                _ => Err(err("Worldpay requires SignatureKey auth type")),
            },
            Connector::Worldpayxml => match auth {
                ConnectorAuthType::SignatureKey {
                    api_key,
                    key1,
                    api_secret,
                } => {
                    let worldpayxml_meta = metadata
                        .map(|m| {
                            serde_json::from_value::<WorldpayxmlMetadata>(m.clone())
                                .map_err(|_| err("Invalid Worldpayxml metadata format"))
                        })
                        .transpose()?;

                    Ok(Self::Worldpayxml {
                        api_username: api_key.clone(),
                        api_password: key1.clone(),
                        merchant_code: api_secret.clone(),
                        issuer_id: worldpayxml_meta.as_ref().and_then(|m| m.issuer_id.clone()),
                        organizational_unit_id: worldpayxml_meta
                            .as_ref()
                            .and_then(|m| m.organizational_unit_id.clone()),
                        jwt_mac_key: worldpayxml_meta.as_ref().and_then(|m| m.jwt_mac_key.clone()),
                    })
                }
                _ => Err(err("Worldpayxml requires SignatureKey auth type")),
            },
            Connector::Zift => match auth {
                ConnectorAuthType::SignatureKey {

View on GitHub (pinned to 3093f22cc4)

Solutions

  1. Inspect the `metadata` JSON value sent for the Worldpayxml merchant connector account and make it match the `WorldpayxmlMetadata` struct (all fields optional strings: issuer_id, organizational_unit_id, jwt_mac_key).
  2. Ensure metadata is a JSON object (not a string or array) and that string-typed fields are not numbers/booleans/null where a string is required.
  3. Remove unknown or misspelled keys from metadata, or temporarily omit metadata entirely — it is optional (`metadata.map(...)`) and omitted metadata is accepted.
  4. If the payload looks correct, deserialize locally against the current `WorldpayxmlMetadata` definition in your Hyperswitch version to see the real serde error (the thrown error hides it).

Example fix

// before
metadata = "{\"issuer_id\": 12345}"  // metadata sent as JSON string with numeric issuer_id
// after
metadata = {"issuer_id": "12345", "organizational_unit_id": "ou-abc"}  // proper object with string values
Defensive patterns

Strategy: validation

Validate before calling

fn validate_worldpayxml_metadata(metadata: &serde_json::Value) -> Result<(), String> {
    if !metadata.is_object() {
        return Err("metadata must be a JSON object".into());
    }
    for key in ["issuer_id", "organizational_unit_id", "jwt_mac_key"] {
        if let Some(v) = metadata.get(key) {
            if !v.is_string() {
                return Err(format!("metadata field '{}' must be a string", key));
            }
        }
    }
    Ok(())
}

Type guard

fn is_valid_worldpayxml_metadata(v: &serde_json::Value) -> bool {
    serde_json::from_value::<WorldpayxmlMetadata>(v.clone()).is_ok()
}

Try / catch

let meta = metadata
    .map(|m| serde_json::from_value::<WorldpayxmlMetadata>(m.clone()))
    .transpose()
    .map_err(|e| report!(WorldpayxmlMetadataError::InvalidFormat).attach_printable(format!("metadata rejected: {}", e)))?;

Prevention

When it happens

Trigger: Calling the connector config conversion (e.g. when creating/updating a merchant connector account or building connector data for Worldpayxml) with `ConnectorAuthType::SignatureKey` and a `metadata` field that is not a valid `WorldpayxmlMetadata` JSON object — e.g. `"issuer_id": 123` (number instead of string), a metadata JSON string instead of an object, or unexpected/invalid fields.

Common situations: Hand-editing connector metadata in the dashboard or via API and mistyping a field name or type; copying metadata from another connector whose schema differs; an API client sending metadata as a JSON-encoded string rather than a nested object; schema changes to WorldpayxmlMetadata between Hyperswitch versions making older payloads invalid.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of juspay/hyperswitch@3093f22cc4 (2026-09-09). Data as JSON: /api/errors/9df1c92362ca70ae. Report an issue: GitHub.