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
- Set Kind to the appropriate value (e.g. "checkout" or "payment") before signing.
- Derive the kind from the calling context (checkout flow vs payment/x402 rail) instead of leaving it unset.
- 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
- Model Kind as a typed enum/constant set instead of a free-form string.
- Derive Kind from the calling flow rather than leaving it to the caller.
- Reject empty kind in JSON unloading with custom UnmarshalJSON validation.
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
- ap2: mandate id is required
- ai model is nil
- ErrEncodingToken
- ErrMissingTopic
- ap2: mandate signature verification failed
AI-assisted analysis of micro/go-micro@24529f1404 (2026-09-01).
Data as JSON: /api/errors/b359ea7cc03f71bd.
Report an issue: GitHub.