JuliusBrussee/caveman · error
objectstore: access key and secret key are required
Error message
objectstore: access key and secret key are required
What it means
validateConfig requires non-empty AccessKey and SecretKey credentials for the S3 backend. Without them the MinIO client cannot authenticate, so configuration fails fast with this error before any connection attempt.
Solutions
- Set both S3_ACCESS_KEY (or S3_ACCESS_KEY_ID) and S3_SECRET_ACCESS_KEY in the environment or Config fields.
- Verify the secret volume/env mapping actually reaches the process (kubectl exec env / docker inspect).
- Check for empty-string values after credential rotation or templating — whitespace-only also fails.
- If credentials are legitimately not needed (anonymous bucket), this store still requires them; supply machine credentials.
Example fix
// before # S3_ACCESS_KEY unset // after export S3_ACCESS_KEY_ID="caveman-svc" export S3_SECRET_ACCESS_KEY="$SECRET_VALUE"
Defensive patterns
Strategy: validation
Validate before calling
if strings.TrimSpace(cfg.AccessKey) == "" || strings.TrimSpace(cfg.SecretKey) == "" {
return errors.New("S3 credentials must be set")
} Try / catch
store, err := objectstore.New(cfg)
if err != nil {
return fmt.Errorf("object store credentials: %w", err)
} Prevention
- Mount credential secrets explicitly and verify with an env dump in the container
- Remember both S3_ACCESS_KEY/S3_SECRET_ACCESS_KEY and AWS-style S3_ACCESS_KEY_ID names are accepted
- Handle empty-string injection from templated secrets after rotation
When it happens
Trigger: Calling New/FromEnv with empty AccessKey or SecretKey (env vars S3_ACCESS_KEY / S3_SECRET_ACCESS_KEY or AWS-conventional S3_ACCESS_KEY_ID / S3_SECRET_ACCESS_KEY unset); whitespace-only credential values (TrimSpace'd); a secret manager that injected empty strings.
Common situations: Deploying with the endpoint/bucket set but the credential secret not mounted; rotating credentials and leaving an env var empty; using AWS-style variable names without knowing both naming conventions are accepted.
Related errors
- caveman agent: multiple provider credentials found; set…
- caveman-code: no supported provider credential found; set…
- objectstore: endpoint and bucket are required
- objectstore: production endpoint must be an HTTPS origin…
- objectstore: production requires TLS
AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20).
Data as JSON: /api/errors/38f85a22c0459674.
Report an issue: GitHub.
Appendix: source
Thrown at shared/platform/objectstore/objectstore.go:193
timeout := time.Duration(env.Int("CAVE_OBJECTSTORE_PROBE_TIMEOUT_MS", 10000)) * time.Millisecond
if timeout <= 0 {
timeout = 10 * time.Second
}
ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
if err := Probe(ctx, store); err != nil {
return nil, fmt.Errorf("objectstore: production read/write/delete probe failed: %w", err)
}
}
return store, nil
}
func validateConfig(cfg Config, production bool) error {
if strings.TrimSpace(cfg.Endpoint) == "" || strings.TrimSpace(cfg.Bucket) == "" {
return errors.New("objectstore: endpoint and bucket are required")
}
if strings.TrimSpace(cfg.AccessKey) == "" || strings.TrimSpace(cfg.SecretKey) == "" {
return errors.New("objectstore: access key and secret key are required")
}
if !production {
return nil
}
if !cfg.UseSSL || strings.HasPrefix(strings.ToLower(strings.TrimSpace(cfg.Endpoint)), "http://") {
return errors.New("objectstore: production requires TLS")
}
raw := strings.TrimSpace(cfg.Endpoint)
if !strings.Contains(raw, "://") {
raw = "https://" + raw
}
u, err := url.Parse(raw)
if err != nil || u.Scheme != "https" || u.Hostname() == "" || u.User != nil || u.RawQuery != "" || u.Fragment != "" || (u.Path != "" && u.Path != "/") {
return errors.New("objectstore: production endpoint must be an HTTPS origin without credentials, path, query, or fragment")
}
return nil
}
View on GitHub (pinned to 3ee70a1026)