{"record":{"id":"6687a68d8372383e","repo":"JuliusBrussee/caveman","slug":"objectstore-s3-endpoint-is-required-in-production","errorCode":null,"errorMessage":"objectstore: S3_ENDPOINT is required in production","messagePattern":"objectstore: S3_ENDPOINT is required in production","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"shared/platform/objectstore/objectstore.go","lineNumber":147,"sourceCode":"\tAccessKey string\n\tSecretKey string\n\tRegion    string\n\tUseSSL    bool\n}\n\n// FromEnv builds a Store from the S3_* environment variables. It returns\n// (nil, nil) when S3_ENDPOINT is unset outside production. Production requires\n// object storage because retention, replay, and artifact offload must not\n// silently disable themselves after launch.\n//\n// Credential vars accept both the repo's names (S3_ACCESS_KEY/S3_SECRET_KEY)\n// and the AWS-conventional names (S3_ACCESS_KEY_ID/S3_SECRET_ACCESS_KEY). TLS is\n// inferred from the endpoint scheme (https) unless S3_USE_SSL forces it.\nfunc FromEnv() (Store, error) {\n\tendpoint := env.String(\"S3_ENDPOINT\", \"\")\n\tif endpoint == \"\" {\n\t\tif env.IsProduction() {\n\t\t\treturn nil, errors.New(\"objectstore: S3_ENDPOINT is required in production\")\n\t\t}\n\t\treturn nil, nil\n\t}\n\tproduction := env.IsProduction()\n\tbucketFallback := \"caveman-local\"\n\tif production {\n\t\tbucketFallback = \"\"\n\t}\n\taccess := env.String(\"S3_ACCESS_KEY\", env.String(\"S3_ACCESS_KEY_ID\", \"\"))\n\tsecret := env.String(\"S3_SECRET_KEY\", env.String(\"S3_SECRET_ACCESS_KEY\", \"\"))\n\tuseSSL := strings.HasPrefix(endpoint, \"https://\") || env.Bool(\"S3_USE_SSL\", false)\n\tcfg := Config{\n\t\tEndpoint:  endpoint,\n\t\tBucket:    env.String(\"S3_BUCKET\", bucketFallback),\n\t\tAccessKey: access,\n\t\tSecretKey: secret,\n\t\tRegion:    env.String(\"S3_REGION\", \"us-east-1\"),\n\t\tUseSSL:    useSSL,","sourceCodeStart":129,"sourceCodeEnd":165,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/3ee70a102609e550bd2e68004bf5990a9341c851/shared/platform/objectstore/objectstore.go#L129-L165","documentation":"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'.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Set S3_ENDPOINT to the MinIO/S3 endpoint URL in the deployment environment.","Confirm the deployment manifest/secret actually injects S3_ENDPOINT into the container env.","Check env.IsProduction(): if this is not meant to be production, fix the environment flag rather than the S3 vars.","If intentionally running without a store in non-production, set the endpoint or accept the (nil, nil) store and guard usage."],"exampleFix":"// before (k8s env)\n# S3_ENDPOINT missing\n// after\nenv:\n  - name: S3_ENDPOINT\n    value: \"minio.internal.example.com:9000\"","handlingStrategy":"validation","validationCode":"if os.Getenv(\"S3_ENDPOINT\") == \"\" && env.IsProduction() {\n    return errors.New(\"refusing to start: S3_ENDPOINT required in production\")\n}","typeGuard":null,"tryCatchPattern":"store, err := objectstore.FromEnv()\nif err != nil {\n    return fmt.Errorf(\"object store init: %w\", err)\n}","preventionTips":["Add S3_ENDPOINT to deployment secrets/configmaps and startup readiness checks","Validate required env vars in CI with a production-mode smoke test","Distinguish the intentional (nil, nil) non-production case from the production error","Document env var names where config is templated"],"tags":["objectstore","configuration","production","env"],"backgroundTag":"missing-env-var","analyzedSha":"3ee70a102609e550bd2e68004bf5990a9341c851","analyzedAt":"2026-09-20T15:53:39.229Z","contentChangedAt":"2026-09-20T15:53:39.229Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}