JuliusBrussee/caveman · critical

production KMS configuration

Error message

production KMS configuration: %w

What it means

RefuseProductionDefaults wraps a failure from kms.ValidateProduction() with the prefix 'production KMS configuration'. In production mode this library refuses to start unless the KMS is properly configured (real key IDs/credentials, not local/placeholder settings). It is thrown so the process fails fast instead of running production traffic against default or unusable KMS settings.

Solutions

  1. Configure the KMS variables kms.ValidateProduction() requires (key ID, region, credentials) with real production values.
  2. Inspect the wrapped cause (%w) in the error chain for the specific KMS problem and fix that first.
  3. If this is not a production deployment, run in local mode where KMS defaults are allowed.
  4. Verify cloud credentials are present in the deployment environment so the real KMS is resolvable.

Example fix

// before
// prod deploy with no KMS key set
CAVE_ENV=production ./cave  // -> production KMS configuration: ...

// after
export CAVE_ENV=production
export CAVE_KMS_KEY_ID=arn:aws:kms:us-east-1:123456789:key/abcd-...
export AWS_REGION=us-east-1
./cave
Defensive patterns

Strategy: validation

Validate before calling

if os.Getenv("CAVE_ENV") == "production" {
    if os.Getenv("CAVE_KMS_KEY_ID") == "" {
        return errors.New("CAVE_KMS_KEY_ID must be set before starting in production")
    }
}
// then call env.RefuseProductionDefaults()

Try / catch

if err := env.RefuseProductionDefaults(); err != nil {
    var kmsErr error
    if errors.As(err, &kmsErr) && strings.Contains(err.Error(), "production KMS configuration") {
        log.Fatalf("fix KMS config: %v", err) // fail fast with the wrapped cause
    }
    return err
}

Prevention

When it happens

Trigger: Calling RefuseProductionDefaults (e.g. at startup with production mode enabled) while kms.ValidateProduction() reports the KMS env/keys are unset, defaulted, or otherwise invalid.

Common situations: Deploying with CAVE_ENV=production but no KMS key configured; copying a local dev compose file to prod; upgrading to a version that added KMS validation; missing cloud credentials so the KMS resolver falls back to defaults.

Understand the failure class

Background: "X is required", "must be set", "cannot be empty": the missing-required-config error family, from Vertex AI project/location to WeChat keys — this error's family across 18 libraries.

Related errors


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

Appendix: source

Thrown at shared/platform/env/env.go:74

// refusals and silently skip the rest. Whitespace and case are therefore folded
// in — the direction that turns MORE deployments on, never fewer.
func IsProduction() bool {
	return runtimeenv.IsProduction()
}

func RefuseProductionDefaults() error {
	if !IsProduction() {
		return nil
	}
	if err := validateProductionTextSecrets([]string{
		"CAVE_KEY_HASH_PEPPER",
		"CAVE_JWT_SIGNING_KEY",
		"CAVE_BOOTSTRAP_TOKEN",
	}); err != nil {
		return err
	}
	if err := kms.ValidateProduction(); err != nil {
		return fmt.Errorf("production KMS configuration: %w", err)
	}
	return validateProductionPublicURL()
}

// RefuseGatewayProductionDefaults validates only material the public data plane
// consumes. Control-plane JWT/bootstrap secrets must never be injected into the
// gateway merely to satisfy a shared configuration check.
func RefuseGatewayProductionDefaults() error {
	if !IsProduction() {
		return nil
	}
	if err := validateProductionTextSecrets([]string{"CAVE_KEY_HASH_PEPPER"}); err != nil {
		return err
	}
	if Bool("CAVE_REPLAY_ENABLED", false) {
		if err := validateProductionTextSecrets([]string{"CAVE_ROUTER_REPLAY_TOKEN"}); err != nil {
			return err
		}

View on GitHub (pinned to 3ee70a1026)