argoproj/argo-workflows · error

EncryptOpts.KmsKeyId and EncryptOpts.SSECPassword cannot be

Error message

EncryptOpts.KmsKeyId and EncryptOpts.SSECPassword cannot be set together

What it means

NewClient rejects S3 encryption options that specify both a KMS key ID (SSE-KMS) and an SSEC password (SSE-C), because an object cannot be encrypted with both mechanisms at once. This is a client-construction validation error and is not retriable.

Source

Thrown at workflow/artifacts/s3/s3.go:525

	switch s3cli.AddressingStyle {
	case PathStyle:
		bucketLookupType = minio.BucketLookupPath
	case VirtualHostedStyle:
		bucketLookupType = minio.BucketLookupDNS
	default:
		bucketLookupType = minio.BucketLookupAuto
	}
	minioOpts := &minio.Options{Creds: credentials, Secure: s3cli.Secure, Transport: opts.Transport, Region: s3cli.Region, BucketLookup: bucketLookupType}
	minioClient, err = minio.New(s3cli.Endpoint, minioOpts)
	if err != nil {
		return nil, err
	}
	if opts.Trace {
		minioClient.TraceOn(os.Stderr)
	}

	if opts.EncryptOpts.KmsKeyID != "" && opts.EncryptOpts.ServerSideCustomerKey != "" {
		return nil, fmt.Errorf("EncryptOpts.KmsKeyId and EncryptOpts.SSECPassword cannot be set together")
	}

	if opts.EncryptOpts.ServerSideCustomerKey != "" && !opts.Secure {
		return nil, fmt.Errorf("secure must be set if EncryptOpts.SSECPassword is set")
	}

	s3cli.ctx = ctx
	s3cli.minioClient = minioClient

	return &s3cli, nil
}

// Gets number of threads for S3 upload from env var. Default if not set: 4.
func (s *s3client) getFromEnvS3UploadNbThreads() int {
	// Minio default threads: https://github.com/minio/minio-go/blob/v7.0.98/constants.go#L58
	const defaultThreads = 4

	nbThreadsStr := os.Getenv(common.EnvVarS3UploadThreads)

View on GitHub (pinned to 35bff19146)

Solutions

  1. Remove either kmsKeyId or ssecPassword from encryptionOptions, keeping only the mechanism you want
  2. If you need SSE-KMS, delete the ssecPassword/encryptionKey setting; if SSE-C, drop kmsKeyId and kmsEncryptionContext
  3. Re-check rendered controller ConfigMap / artifact spec to confirm only one option remains

Example fix

// before
encryptionOptions:
  kmsKeyId: alias/aws/s3
  ssecPasswordSecret: {name: my-secret, key: password}
// after
encryptionOptions:
  kmsKeyId: alias/aws/s3
Defensive patterns

Strategy: validation

Validate before calling

func validateEncOpts(o s3.EncryptOpts) error {
  if o.KmsKeyID != "" && o.ServerSideCustomerKey != "" {
    return errors.New("set only one of kmsKeyId or ssecPassword")
  }
  return nil
}

Type guard

func hasConflictingEncOpts(o s3.EncryptOpts) bool {
  return o.KmsKeyID != "" && o.ServerSideCustomerKey != ""
}

Try / catch

if _, err := s3.NewClient(ctx, opts); err != nil && strings.Contains(err.Error(), "cannot be set together") {
  // strip one of the encryption options and rebuild
}

Prevention

When it happens

Trigger: The artifact's S3 encryptionOptions set both kmsKeyId and ssecPassword (via artifact repository config or per-artifact encryptionOptions), then NewClient is invoked.

Common situations: Copying an example config that had one option and adding the other; templating both fields from values files where both secrets happen to be populated; merging operator and user config each contributing a different option.

Related errors


AI-assisted analysis of argoproj/argo-workflows@35bff19146 (2026-09-03). Data as JSON: /api/errors/12dbc7b086a143c5. Report an issue: GitHub.