{"record":{"id":"75c52383a888077f","repo":"k3s-io/k3s","slug":"s3-configuration-was-not-set","errorCode":null,"errorMessage":"s3 configuration was not set","messagePattern":"s3 configuration was not set","errorType":"validation","errorClass":null,"httpStatus":400,"severity":"error","filePath":"pkg/etcd/s3/s3.go","lineNumber":150,"sourceCode":"\t// also ignore retention, as it may have been defaulted from the etcd-snapshot-retention flag.\n\tdefaultEtcdS3.Retention = etcdS3.Retention\n\n\t// If config is default, try to load config from secret, and fail if it cannot be retrieved or if the secret name is not set.\n\t// If config is not default, and secret name is set, warn that the secret is being ignored\n\tisDefault := reflect.DeepEqual(defaultEtcdS3, etcdS3)\n\tif etcdS3.ConfigSecret != \"\" {\n\t\tif isDefault {\n\t\t\te, err := c.getConfigFromSecret(etcdS3.ConfigSecret)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, errors.WithMessagef(err, \"failed to get config from etcd-s3-config-secret %q\", etcdS3.ConfigSecret)\n\t\t\t}\n\t\t\tlogrus.Infof(\"Using etcd s3 configuration from etcd-s3-config-secret %q\", etcdS3.ConfigSecret)\n\t\t\tetcdS3 = e\n\t\t} else {\n\t\t\tlogrus.Warnf(\"Ignoring s3 configuration from etcd-s3-config-secret %q due to existing configuration from CLI or config file\", etcdS3.ConfigSecret)\n\t\t}\n\t} else if isDefault {\n\t\treturn nil, errors.New(\"s3 configuration was not set\")\n\t}\n\n\t// used just for logging\n\tscheme := \"https://\"\n\tif etcdS3.Insecure {\n\t\tscheme = \"http://\"\n\t}\n\n\t// Try to get an existing client from cache.  The entire EtcdS3 struct\n\t// (including the key id and secret) is used as the cache key, but we only\n\t// print the endpoint and bucket name to avoid leaking creds into the logs.\n\tif client, ok := c.clientCache.Get(*etcdS3); ok {\n\t\tlogrus.Infof(\"Reusing cached S3 client for endpoint=%q bucket=%q folder=%q\", scheme+etcdS3.Endpoint, etcdS3.Bucket, etcdS3.Folder)\n\t\treturn client, nil\n\t}\n\tlogrus.Infof(\"Attempting to create new S3 client for endpoint=%q bucket=%q folder=%q\", scheme+etcdS3.Endpoint, etcdS3.Bucket, etcdS3.Folder)\n\n\tif etcdS3.Bucket == \"\" {","sourceCodeStart":132,"sourceCodeEnd":168,"githubUrl":"https://github.com/k3s-io/k3s/blob/6ba341e396edc16b8dcae978a7c5e3ac7ee5606e/pkg/etcd/s3/s3.go#L132-L168","documentation":"When building an S3 client, the code first honors CLI/config-file settings; only if none were provided (isDefault) does it fall back to an etcd-s3-config-secret. If neither source exists it returns 's3 configuration was not set' rather than dialing S3 with empty credentials.","triggerScenarios":"Invoking any S3-backed etcd operation (--etcd-snapshot-save --s3, list, prune, restore) with no --etcd-s3-* flags and no etcd-s3-config-secret reference, while the code path is marked as requiring a usable default configuration.","commonSituations":"Adding --s3 to snapshot commands without configuring endpoint/bucket/credentials; relying on a config secret that was deleted or whose name flag (--etcd-s3-config-secret) is misspelled; splitting flags between config file and CLI such that the default branch is taken.","solutions":["Provide the S3 settings via CLI/config file: --etcd-s3-endpoint, --etcd-s3-bucket-name, --etcd-s3-access-key, --etcd-s3-secret-key.","Or create the etcd-s3-config secret in kube-system and reference it with --etcd-s3-config-secret=<name>; the secret must contain the s3 keys as data fields.","If you did not intend S3 at all, drop the --s3 / s3 flags from the etcd-snapshot command."],"exampleFix":"# before\nk3s etcd-snapshot save --s3\n# after\nk3s etcd-snapshot save --s3 \\\n  --etcd-s3-endpoint=s3.amazonaws.com \\\n  --etcd-s3-bucket-name=my-bucket \\\n  --etcd-s3-access-key=AKIA... --etcd-s3-secret-key=...","handlingStrategy":"validation","validationCode":"func s3Configured(cfg *config.Control) bool {\n\tif cfg.EtcdS3 == nil {\n\t\treturn false\n\t}\n\treturn cfg.EtcdS3.Endpoint != \"\" || cfg.EtcdS3.Bucket != \"\" || cfg.EtcdS3.ConfigSecret != \"\"\n}","typeGuard":null,"tryCatchPattern":"if _, err := e.getS3Client(ctx); err != nil {\n    if strings.Contains(err.Error(), \"s3 configuration was not set\") {\n        // configuration gap: fail loudly in automation, do not retry\n    }\n    return err\n}","preventionTips":["Templated config: assert at least endpoint+bucket+credentials or a config-secret name before deploying.","Prefer the etcd-s3-config-secret so credentials and required fields live in one audited object."],"tags":["s3","etcd","configuration","backup"],"backgroundTag":null,"analyzedSha":"6ba341e396edc16b8dcae978a7c5e3ac7ee5606e","analyzedAt":"2026-08-15T16:27:54.286Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}