diem/diem · error

Signing multi agent txn failed

Error message

Signing multi agent txn failed

What it means

LocalAccount::sign_multi_agent_with_transaction_builder unwraps RawTransaction::sign_multi_agent with a generic 'Signing multi agent txn failed' message. sign_multi_agent validates signer consistency (primary key matches sender, secondary keys match addresses); any mismatch makes it return an error, and this helper turns that into a panic.

Source

Thrown at sdk/src/types.rs:87

            .iter()
            .map(|signer| signer.address())
            .collect();
        let secondary_signer_privkeys = secondary_signers
            .iter()
            .map(|signer| signer.private_key())
            .collect();
        let raw_txn = builder
            .sender(self.address())
            .sequence_number(self.sequence_number())
            .build();
        *self.sequence_number_mut() += 1;
        raw_txn
            .sign_multi_agent(
                self.private_key(),
                secondary_signer_addresses,
                secondary_signer_privkeys,
            )
            .expect("Signing multi agent txn failed")
            .into_inner()
    }

    pub fn address(&self) -> AccountAddress {
        self.address
    }

    pub fn private_key(&self) -> &Ed25519PrivateKey {
        self.key.private_key()
    }

    pub fn public_key(&self) -> &Ed25519PublicKey {
        self.key.public_key()
    }

    pub fn authentication_key(&self) -> AuthenticationKey {
        self.key.authentication_key()
    }

View on GitHub (pinned to fc4714a8ea)

Solutions

  1. Verify every (address, private_key) pair matches: derive the address from each private key and compare
  2. Confirm the primary signer (self) is actually the transaction sender of the raw_txn
  3. Check secondary_signer_addresses and secondary_signer_privkeys are the same length and in the same order
  4. Use RawTransaction::sign_multi_agent directly for fallible handling instead of the expect-based helper

Example fix

// before
let signed = account.sign_multi_agent_with_transaction_builder(builder, secondary_addrs, secondary_keys);
// after
assert_eq!(account.address(), raw_txn.sender(), "primary signer must be sender");
for (a, k) in secondary_addrs.iter().zip(secondary_keys) {
    assert_eq!(a, &diem_crypto::PrivateKey::public_key_for(k).into(), "key/address mismatch");
}
let signed = account.sign_multi_agent_with_transaction_builder(builder, secondary_addrs, secondary_keys);
Defensive patterns

Strategy: validation

Validate before calling

fn validate_signers(
    sender: AccountAddress,
    primary: &Ed25519PrivateKey,
    secondary: &[(AccountAddress, Ed25519PrivateKey)],
) -> bool {
    if AccountAddress::from(Ed25519PublicKey::from(primary)) != sender {
        return false;
    }
    secondary.iter().all(|(addr, key)| {
        &AccountAddress::from(Ed25519PublicKey::from(key)) == addr
    })
}

Try / catch

// prefer the fallible API over the expect-based helper
let signed = raw_txn
    .sign_multi_agent(
        account.private_key(),
        secondary_addrs,
        secondary_keys,
    )
    .map_err(|e| anyhow!("multi-agent signing failed: {}", e))?
    .into_inner();

Prevention

When it happens

Trigger: Calling sign_multi_agent_with_transaction_builder where the primary private key does not correspond to the raw transaction's sender, or a secondary private key does not correspond to its paired secondary address.

Common situations: Swapped address/key pairs in the secondary signer arrays; sender address derived from a different key than self; building multi-agent payloads with accounts loaded in the wrong order.

Related errors


AI-assisted analysis of diem/diem@fc4714a8ea (2026-09-04). Data as JSON: /api/errors/801c27e3379dc706. Report an issue: GitHub.