Tencent/WeKnora · error
S3 access key and secret key must be provided together
Error message
S3 access key and secret key must be provided together
What it means
newS3Client supports two credential modes: AWS default credential chain (no AK/SK) or explicit static credentials. This error means exactly one of accessKey/secretKey was provided while the other was empty, which is an ambiguous, unsupported configuration.
Source
Thrown at internal/application/service/file/s3.go:46
bucketName string
pathPrefix string
}
// newS3Client creates a bare s3FileService with just the SDK client initialised.
func newS3Client(endpoint, accessKey, secretKey, bucketName, region, pathPrefix string, forcePathStyle bool) (*s3FileService, error) {
if err := utils.ValidateURLForSSRF(endpoint); err != nil {
return nil, fmt.Errorf("unsafe S3 endpoint: %w", err)
}
var cfg aws.Config
var err error
// With no explicit AK/SK, keep the AWS default credential chain intact. This
// supports IAM roles for EC2/ECS/EKS (IRSA), web identity, shared config, and
// environment credentials without persisting long-lived keys in WeKnora.
loadOptions := []func(*config.LoadOptions) error{config.WithRegion(region)}
if accessKey != "" || secretKey != "" {
if accessKey == "" || secretKey == "" {
return nil, fmt.Errorf("S3 access key and secret key must be provided together")
}
loadOptions = append(loadOptions, config.WithCredentialsProvider(
credentials.NewStaticCredentialsProvider(accessKey, secretKey, ""),
))
}
cfg, err = config.LoadDefaultConfig(context.Background(), loadOptions...)
if err != nil {
return nil, fmt.Errorf("failed to load AWS config: %w", err)
}
// Create S3 client with custom endpoint if provided.
// For S3-compatible services (non-AWS), use path-style addressing
// (endpoint/bucket/key) instead of virtual-hosted style (bucket.endpoint/key).
httpClient := utils.NewSSRFSafeHTTPClient(utils.DefaultSSRFSafeHTTPClientConfig())
var client *s3.Client
if endpoint != "" {
usePathStyle := forcePathStyle || !strings.Contains(endpoint, "amazonaws.com")View on GitHub (pinned to 988cbb0330)
Solutions
- Provide both accessKey and secretKey together, or leave both empty to use the AWS default credential chain (IAM role, env, shared config)
- Audit your config source — a secret-injection tool likely dropped or blanked one key
- If you intend IRSA/instance-profile auth, remove the single leftover key
Example fix
// before NewS3FileService(endpoint, "AKIA...", "", bucket, region, prefix) // error // after NewS3FileService(endpoint, "AKIA...", "secret...", bucket, region, prefix) // or "", "" for default chain
Defensive patterns
Strategy: validation
Validate before calling
if (accessKey == "") != (secretKey == "") {
return errors.New("S3 access key and secret key must be provided together")
} Prevention
- Store AK/SK as a paired secret (single secret-manager entry)
- Validate credential pairs in config-loading code before calling NewS3FileService
- Prefer the default credential chain (IAM roles) over static keys
- Add startup config linting that flags half-set credentials
When it happens
Trigger: Setting S3_ACCESS_KEY without S3_SECRET_KEY (or vice versa) in configuration passed to NewS3FileService / NewS3FileServiceWithOptions / CheckS3ConnectivityWithOptions.
Common situations: Partial config updates where one of the two keys was rotated or redacted by a deployment tool, secret manager returning empty for one key, YAML/env template with only one key filled in.
Related errors
- failed to load AWS config: %w
- sandbox: config is missing required fields
- E2BAPIKey is required for the E2B backend
- unsafe S3 endpoint: %w
- s3 copy rejected source %q: %w
AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02).
Data as JSON: /api/errors/bdaeebd9837ac7fe.
Report an issue: GitHub.