JuliusBrussee/caveman · critical

objectstore: S3_ENDPOINT is required in production

Error message

objectstore: S3_ENDPOINT is required in production

What it means

FromEnv returns this error when S3_ENDPOINT is empty and the process is running in production (env.IsProduction()). In production the object store must be explicitly configured — silently defaulting to a local bucket would be unsafe — while in non-production it returns (nil, nil) meaning 'no store configured'.

Solutions

  1. Set S3_ENDPOINT to the MinIO/S3 endpoint URL in the deployment environment.
  2. Confirm the deployment manifest/secret actually injects S3_ENDPOINT into the container env.
  3. Check env.IsProduction(): if this is not meant to be production, fix the environment flag rather than the S3 vars.
  4. If intentionally running without a store in non-production, set the endpoint or accept the (nil, nil) store and guard usage.

Example fix

// before (k8s env)
# S3_ENDPOINT missing
// after
env:
  - name: S3_ENDPOINT
    value: "minio.internal.example.com:9000"
Defensive patterns

Strategy: validation

Validate before calling

if os.Getenv("S3_ENDPOINT") == "" && env.IsProduction() {
    return errors.New("refusing to start: S3_ENDPOINT required in production")
}

Try / catch

store, err := objectstore.FromEnv()
if err != nil {
    return fmt.Errorf("object store init: %w", err)
}

Prevention

When it happens

Trigger: Deploying a service with S3_ENDPOINT unset/empty while the production environment flag is active (e.g. CAVE_ENV=production); a mis-deployed config where the env var was dropped; running the production binary locally without realizing it detects production mode.

Common situations: Kubernetes/container deploys missing the S3_ENDPOINT entry in the secret or configmap; renaming the env var during a config refactor; CI jobs running with production env flags but no S3 settings.

Understand the failure class

Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.

Related errors


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

Appendix: source

Thrown at shared/platform/objectstore/objectstore.go:147

	AccessKey string
	SecretKey string
	Region    string
	UseSSL    bool
}

// FromEnv builds a Store from the S3_* environment variables. It returns
// (nil, nil) when S3_ENDPOINT is unset outside production. Production requires
// object storage because retention, replay, and artifact offload must not
// silently disable themselves after launch.
//
// Credential vars accept both the repo's names (S3_ACCESS_KEY/S3_SECRET_KEY)
// and the AWS-conventional names (S3_ACCESS_KEY_ID/S3_SECRET_ACCESS_KEY). TLS is
// inferred from the endpoint scheme (https) unless S3_USE_SSL forces it.
func FromEnv() (Store, error) {
	endpoint := env.String("S3_ENDPOINT", "")
	if endpoint == "" {
		if env.IsProduction() {
			return nil, errors.New("objectstore: S3_ENDPOINT is required in production")
		}
		return nil, nil
	}
	production := env.IsProduction()
	bucketFallback := "caveman-local"
	if production {
		bucketFallback = ""
	}
	access := env.String("S3_ACCESS_KEY", env.String("S3_ACCESS_KEY_ID", ""))
	secret := env.String("S3_SECRET_KEY", env.String("S3_SECRET_ACCESS_KEY", ""))
	useSSL := strings.HasPrefix(endpoint, "https://") || env.Bool("S3_USE_SSL", false)
	cfg := Config{
		Endpoint:  endpoint,
		Bucket:    env.String("S3_BUCKET", bucketFallback),
		AccessKey: access,
		SecretKey: secret,
		Region:    env.String("S3_REGION", "us-east-1"),
		UseSSL:    useSSL,

View on GitHub (pinned to 3ee70a1026)