k3s-io/k3s · error

s3 configuration was not set

Error message

s3 configuration was not set

What it means

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.

Source

Thrown at pkg/etcd/s3/s3.go:150

	// also ignore retention, as it may have been defaulted from the etcd-snapshot-retention flag.
	defaultEtcdS3.Retention = etcdS3.Retention

	// 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.
	// If config is not default, and secret name is set, warn that the secret is being ignored
	isDefault := reflect.DeepEqual(defaultEtcdS3, etcdS3)
	if etcdS3.ConfigSecret != "" {
		if isDefault {
			e, err := c.getConfigFromSecret(etcdS3.ConfigSecret)
			if err != nil {
				return nil, errors.WithMessagef(err, "failed to get config from etcd-s3-config-secret %q", etcdS3.ConfigSecret)
			}
			logrus.Infof("Using etcd s3 configuration from etcd-s3-config-secret %q", etcdS3.ConfigSecret)
			etcdS3 = e
		} else {
			logrus.Warnf("Ignoring s3 configuration from etcd-s3-config-secret %q due to existing configuration from CLI or config file", etcdS3.ConfigSecret)
		}
	} else if isDefault {
		return nil, errors.New("s3 configuration was not set")
	}

	// used just for logging
	scheme := "https://"
	if etcdS3.Insecure {
		scheme = "http://"
	}

	// Try to get an existing client from cache.  The entire EtcdS3 struct
	// (including the key id and secret) is used as the cache key, but we only
	// print the endpoint and bucket name to avoid leaking creds into the logs.
	if client, ok := c.clientCache.Get(*etcdS3); ok {
		logrus.Infof("Reusing cached S3 client for endpoint=%q bucket=%q folder=%q", scheme+etcdS3.Endpoint, etcdS3.Bucket, etcdS3.Folder)
		return client, nil
	}
	logrus.Infof("Attempting to create new S3 client for endpoint=%q bucket=%q folder=%q", scheme+etcdS3.Endpoint, etcdS3.Bucket, etcdS3.Folder)

	if etcdS3.Bucket == "" {

View on GitHub (pinned to 6ba341e396)

Solutions

  1. Provide the S3 settings via CLI/config file: --etcd-s3-endpoint, --etcd-s3-bucket-name, --etcd-s3-access-key, --etcd-s3-secret-key.
  2. 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.
  3. If you did not intend S3 at all, drop the --s3 / s3 flags from the etcd-snapshot command.

Example fix

# before
k3s etcd-snapshot save --s3
# after
k3s etcd-snapshot save --s3 \
  --etcd-s3-endpoint=s3.amazonaws.com \
  --etcd-s3-bucket-name=my-bucket \
  --etcd-s3-access-key=AKIA... --etcd-s3-secret-key=...
Defensive patterns

Strategy: validation

Validate before calling

func s3Configured(cfg *config.Control) bool {
	if cfg.EtcdS3 == nil {
		return false
	}
	return cfg.EtcdS3.Endpoint != "" || cfg.EtcdS3.Bucket != "" || cfg.EtcdS3.ConfigSecret != ""
}

Try / catch

if _, err := e.getS3Client(ctx); err != nil {
    if strings.Contains(err.Error(), "s3 configuration was not set") {
        // configuration gap: fail loudly in automation, do not retry
    }
    return err
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of k3s-io/k3s@6ba341e396 (2026-08-15). Data as JSON: /api/errors/75c52383a888077f. Report an issue: GitHub.