{"record":{"id":"2a5ebad63df495ab","repo":"JuliusBrussee/caveman","slug":"objectstore-production-read-write-delete-probe-fa","errorCode":null,"errorMessage":"objectstore: production read/write/delete probe failed: %w","messagePattern":"objectstore: production read/write/delete probe failed: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"shared/platform/objectstore/objectstore.go","lineNumber":182,"sourceCode":"\t\tRegion:    env.String(\"S3_REGION\", \"us-east-1\"),\n\t\tUseSSL:    useSSL,\n\t}\n\tif err := validateConfig(cfg, production); err != nil {\n\t\treturn nil, err\n\t}\n\tstore, err := New(cfg)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif production {\n\t\ttimeout := time.Duration(env.Int(\"CAVE_OBJECTSTORE_PROBE_TIMEOUT_MS\", 10000)) * time.Millisecond\n\t\tif timeout <= 0 {\n\t\t\ttimeout = 10 * time.Second\n\t\t}\n\t\tctx, cancel := context.WithTimeout(context.Background(), timeout)\n\t\tdefer cancel()\n\t\tif err := Probe(ctx, store); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"objectstore: production read/write/delete probe failed: %w\", err)\n\t\t}\n\t}\n\treturn store, nil\n}\n\nfunc validateConfig(cfg Config, production bool) error {\n\tif strings.TrimSpace(cfg.Endpoint) == \"\" || strings.TrimSpace(cfg.Bucket) == \"\" {\n\t\treturn errors.New(\"objectstore: endpoint and bucket are required\")\n\t}\n\tif strings.TrimSpace(cfg.AccessKey) == \"\" || strings.TrimSpace(cfg.SecretKey) == \"\" {\n\t\treturn errors.New(\"objectstore: access key and secret key are required\")\n\t}\n\tif !production {\n\t\treturn nil\n\t}\n\tif !cfg.UseSSL || strings.HasPrefix(strings.ToLower(strings.TrimSpace(cfg.Endpoint)), \"http://\") {\n\t\treturn errors.New(\"objectstore: production requires TLS\")\n\t}","sourceCodeStart":164,"sourceCodeEnd":200,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/3ee70a102609e550bd2e68004bf5990a9341c851/shared/platform/objectstore/objectstore.go#L164-L200","documentation":"FromEnv wraps a failed Probe with 'objectstore: production read/write/delete probe failed:'. In production mode the library deliberately proves the bucket actually accepts Put/Get/Delete (and version purge) at startup instead of trusting a syntactically valid config, so misconfigured buckets fail loudly at boot.","triggerScenarios":"Calling objectstore.FromEnv with production mode enabled (e.g. CAVE_ENV=production) where the bucket does not exist, credentials lack put/get/delete permissions, the endpoint is unreachable, or the bucket lacks required versioning — Probe returns an error which is wrapped.","commonSituations":"MinIO/S3 endpoint typo, wrong access/secret keys, IAM policy missing s3:PutObject or s3:DeleteObject, bucket created without versioning, DNS/firewall blocking the storage endpoint, CAVE_OBJECTSTORE_PROBE_TIMEOUT too small for a slow endpoint.","solutions":["Check the wrapped cause (%w) for the concrete failure: connection refused vs access denied vs missing bucket.","Create the configured bucket and enable versioning if the deployment requires it.","Fix credentials/IAM so the configured keys can Put, Get, and Delete objects.","Verify endpoint/SSL settings (CAVE_OBJECTSTORE_ENDPOINT, USE_SSL) and network reachability from the service.","Increase the probe timeout env if the endpoint is slow but reachable."],"exampleFix":"// before\nCAVE_OBJECTSTORE_ENDPOINT=minio.internal:9000  // unreachable; probe fails at startup\n// after\nCAVE_OBJECTSTORE_ENDPOINT=minio.default.svc.cluster.local:9000\nCAVE_OBJECTSTORE_ACCESS_KEY=...  // with s3:PutObject/GetObject/DeleteObject on the bucket\nCAVE_OBJECTSTORE_BUCKET=app-artifacts  // bucket exists and is versioned","handlingStrategy":"try-catch","validationCode":"// pre-flight outside the library\nctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)\ndefer cancel()\nmc, _ := minio.New(endpoint, &minio.Options{Creds: credentials.NewStaticV4(ak, sk, \"\"), Secure: useSSL})\nif _, err := mc.BucketExists(ctx, bucket); err != nil {\n    return fmt.Errorf(\"bucket %q unreachable before startup: %w\", bucket, err)\n}","typeGuard":null,"tryCatchPattern":"store, err := objectstore.FromEnv(ctx)\nif err != nil {\n    var probeErr = err // wrapped Probe failure\n    return fmt.Errorf(\"object store not usable (bucket/creds/endpoint): %w\", probeErr)\n}","preventionTips":["Create and version the bucket in infrastructure-as-code before deploying.","Grant the static keys Put/Get/Delete on the bucket via IAM policy.","Verify endpoint and UseSSL settings match the deployment (no scheme in endpoint).","Smoke-test storage connectivity in CI against the same env config."],"tags":["objectstore","startup-probe","s3","minio"],"backgroundTag":"http-error-response","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"}