micro/go-micro · error

ap2: mandate kind is required

Error message

ap2: mandate kind is required

What it means

SignAP2Mandate requires the mandate's Kind field to be non-empty because the kind (e.g. checkout vs payment mandate) is part of the signed payload and tells verifiers what type of AP2 credential they are checking. An empty Kind would produce an ambiguous, unverifiable credential, so signing is refused.

Source

Thrown at gateway/a2a/ap2.go:71

type AP2Verification struct {
	MandateID string `json:"mandateId"`
	Kind      string `json:"kind"`
	Verified  bool   `json:"verified"`
	Error     string `json:"error,omitempty"`
}

// NewAP2Keypair returns an Ed25519 keypair suitable for tests or local demos.
func NewAP2Keypair() (ed25519.PublicKey, ed25519.PrivateKey, error) {
	return ed25519.GenerateKey(rand.Reader)
}

// SignAP2Mandate signs a mandate as a verifiable AP2 credential.
func SignAP2Mandate(m AP2Mandate, keyID string, private ed25519.PrivateKey) (AP2SignedMandate, error) {
	if m.ID == "" {
		return AP2SignedMandate{}, errors.New("ap2: mandate id is required")
	}
	if m.Kind == "" {
		return AP2SignedMandate{}, errors.New("ap2: mandate kind is required")
	}
	if m.IssuedAt.IsZero() {
		m.IssuedAt = time.Now().UTC()
	}
	payload, err := ap2Payload(m)
	if err != nil {
		return AP2SignedMandate{}, err
	}
	return AP2SignedMandate{Mandate: m, KeyID: keyID, Signature: base64.RawURLEncoding.EncodeToString(ed25519.Sign(private, payload))}, nil
}

// VerifyAP2Mandate verifies a signed mandate credential.
func VerifyAP2Mandate(s AP2SignedMandate, public ed25519.PublicKey) error {
	sig, err := base64.RawURLEncoding.DecodeString(s.Signature)
	if err != nil {
		return fmt.Errorf("ap2: invalid signature encoding: %w", err)
	}
	payload, err := ap2Payload(s.Mandate)

View on GitHub (pinned to 24529f1404)

Solutions

  1. Set Kind to the appropriate value (e.g. "checkout" or "payment") before signing.
  2. Derive the kind from the calling context (checkout flow vs payment/x402 rail) instead of leaving it unset.
  3. Validate the kind at the API boundary that accepts mandate input.

Example fix

// before
m := ap2.AP2Mandate{ID: id} // Kind empty
signed, err := ap2.SignAP2Mandate(m, keyID, priv)

// after
m := ap2.AP2Mandate{ID: id, Kind: "checkout"}
signed, err := ap2.SignAP2Mandate(m, keyID, priv)
Defensive patterns

Strategy: validation

Validate before calling

validKinds := map[string]bool{"checkout": true, "payment": true}
if !validKinds[m.Kind] {
	return fmt.Errorf("cannot sign mandate: Kind must be one of checkout|payment")
}

Try / catch

if _, err := ap2.SignAP2Mandate(m, keyID, priv); err != nil {
	if strings.Contains(err.Error(), "mandate kind is required") {
		// set the kind based on flow and retry once
	}
}

Prevention

When it happens

Trigger: Calling SignAP2Mandate with an AP2Mandate where ID is set but Kind is the empty string — the second guard in the validation chain.

Common situations: Constructing mandates without knowing which kind to use; copying struct literals between checkout and payment flows and dropping the Kind; JSON inputs lacking the kind key.

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 micro/go-micro@24529f1404 (2026-09-01). Data as JSON: /api/errors/b359ea7cc03f71bd. Report an issue: GitHub.