argoproj/argo-workflows · error

failed to create bucket %s: %w

Error message

failed to create bucket %s: %w

What it means

When CreateBucketIfNotPresent is set, the driver calls MakeBucket before uploading. This error wraps a MakeBucket failure that was NOT an already-exists error — the bucket could not be created and the upload was aborted.

Source

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

	isDir, err := file.IsDirectory(path)
	if err != nil {
		return true, fmt.Errorf("failed to test if %s is a directory: %w", path, err)
	}
	log := logging.RequireLoggerFromContext(ctx)
	createBucketIfNotPresent := outputArtifact.S3.CreateBucketIfNotPresent
	if createBucketIfNotPresent != nil {
		log.WithField("bucket", outputArtifact.S3.Bucket).Info(ctx, "creating bucket")
		makeBucketErr := s3cli.MakeBucket(outputArtifact.S3.Bucket, minio.MakeBucketOptions{
			Region:        outputArtifact.S3.Region,
			ObjectLocking: outputArtifact.S3.CreateBucketIfNotPresent.ObjectLocking,
		})
		alreadyExists := bucketAlreadyExistsErr(makeBucketErr)
		log.WithField("bucket", outputArtifact.S3.Bucket).
			WithField("alreadyExists", alreadyExists).
			WithError(makeBucketErr).
			Info(ctx, "create bucket failed")
		if makeBucketErr != nil && !alreadyExists {
			return !isTransientS3Err(ctx, makeBucketErr), fmt.Errorf("failed to create bucket %s: %w", outputArtifact.S3.Bucket, makeBucketErr)
		}
	}

	if isDir {
		if err = s3cli.PutDirectory(outputArtifact.S3.Bucket, outputArtifact.S3.Key, path); err != nil {
			return !isTransientS3Err(ctx, err), fmt.Errorf("failed to put directory: %w", err)
		}
	} else {
		if err = s3cli.PutFile(outputArtifact.S3.Bucket, outputArtifact.S3.Key, path); err != nil {
			return !isTransientS3Err(ctx, err), fmt.Errorf("failed to put file: %w", err)
		}
	}
	return true, nil
}

func bucketAlreadyExistsErr(err error) bool {
	resp := &minio.ErrorResponse{}
	// https://docs.aws.amazon.com/AmazonS3/latest/API/ErrorResponses.html

View on GitHub (pinned to 35bff19146)

Solutions

  1. Read the wrapped minio error to get the exact S3 error code
  2. Grant s3:CreateBucket, or pre-create the bucket and remove CreateBucketIfNotPresent
  3. Fix the bucket name to valid S3 naming (lowercase, 3-63 chars)
  4. Disable objectLocking if the target (e.g. MinIO) doesn't support it
  5. Match the region to the endpoint, or omit region for MinIO

Example fix

# before
createBucketIfNotPresent:
  objectLocking: true   # unsupported by MinIO
# after
createBucketIfNotPresent: {}
Defensive patterns

Strategy: try-catch

Validate before calling

// verify bucket name validity and CreateBucket permission up front
const bucketRE = `^[a-z0-9][a-z0-9.-]{1,61}[a-z0-9]$`
matched, _ := regexp.MatchString(bucketRE, bucket)
if !matched { return fmt.Errorf("invalid bucket name %q", bucket) }

Try / catch

err := s3Driver.Save(ctx, path, art)
if err != nil && strings.Contains(err.Error(), "failed to create bucket") {
    // pre-create the bucket out-of-band and remove CreateBucketIfNotPresent
}

Prevention

When it happens

Trigger: saveS3Artifact with createBucketIfNotPresent set: s3cli.MakeBucket(bucket, opts) failed for reasons other than BucketAlreadyExists/BucketAlreadyOwnedByYou — permission denied, invalid bucket name, region mismatch, or object-locking unsupported on the endpoint.

Common situations: Credentials lacking s3:CreateBucket; bucket name violating S3 naming rules (uppercase, too long); MinIO endpoints not supporting ObjectLocking; region specified that the endpoint doesn't serve; AWS account bucket limits reached.

Related errors


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