JuliusBrussee/caveman · error

kms: probe decrypt

Error message

kms: probe decrypt: %w

What it means

Probe completes its round trip by Decrypting the envelope it just encrypted; any Decrypt failure is re-wrapped as "kms: probe decrypt: %w". A failure here means the key cannot decrypt data it just encrypted — usually an API, permission, or envelope-validation problem on the decrypt path.

Solutions

  1. Unwrap the error chain to find which Decrypt validation failed (provider, location, API, or network).
  2. Check IAM/key policy grants decrypt (not just encrypt) for the token in use.
  3. Confirm no key deletion/rotation raced between the Encrypt and Decrypt inside Probe.
  4. Verify client region/keyID match where the key actually lives; re-Probe after fixes.

Example fix

// before
err := client.Probe(ctx) // kms: probe decrypt: kms: envelope provider does not match...
// after
if err := client.Probe(ctx); err != nil {
    if strings.Contains(err.Error(), "probe decrypt") {
        log.Println("decrypt path broken: check decrypt IAM grants and key state")
    }
    return err
}
Defensive patterns

Strategy: try-catch

Validate before calling

if err := client.Probe(ctx); err != nil && strings.Contains(err.Error(), "probe decrypt") {
    return errors.New("decrypt path broken: verify key grants include decrypt")
}

Try / catch

if err := client.Probe(ctx); err != nil {
    switch {
    case strings.Contains(err.Error(), "probe encrypt"):
        log.Println("KMS write path failing")
    case strings.Contains(err.Error(), "probe decrypt"):
        log.Println("KMS read path failing: check decrypt IAM grants")
    }
    return err
}

Prevention

When it happens

Trigger: Calling Probe when the inner Decrypt fails: envelope size limit, JSON decode failure, provider mismatch, validateLocation rejecting the envelope's region/keyID, or decrypt API/network errors via client.call.

Common situations: Key rotation removing the key between the two calls; per-operation IAM (encrypt allowed, decrypt denied); envelope byte corruption in transport within the probe; region mismatch between client config and API response.

Related errors


AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20). Data as JSON: /api/errors/beb64bf2c6c0dd71. Report an issue: GitHub.

Appendix: source

Thrown at shared/platform/kms/kms.go:328

	if err != nil {
		return err
	}
	return client.Probe(ctx)
}

// Probe verifies live key access without persisting tenant data.
func (c *Client) Probe(ctx context.Context) error {
	plaintext := make([]byte, 32)
	if _, err := rand.Read(plaintext); err != nil {
		return fmt.Errorf("kms: generate probe: %w", err)
	}
	envelope, err := c.Encrypt(ctx, plaintext)
	if err != nil {
		return fmt.Errorf("kms: probe encrypt: %w", err)
	}
	decrypted, err := c.Decrypt(ctx, envelope)
	if err != nil {
		return fmt.Errorf("kms: probe decrypt: %w", err)
	}
	if !bytes.Equal(decrypted, plaintext) {
		return errors.New("kms: probe plaintext mismatch")
	}
	return nil
}

func validateLocation(region, keyID string) error {
	if !regionPattern.MatchString(region) {
		return errors.New("kms: invalid Scaleway region")
	}
	if !keyIDPattern.MatchString(keyID) {
		return errors.New("kms: invalid Scaleway key ID")
	}
	return nil
}

func (c *Client) call(ctx context.Context, region, keyID, operation string, input, output any) error {

View on GitHub (pinned to 3ee70a1026)