{"record":{"id":"64e050edae84ea30","repo":"argoproj/argo-workflows","slug":"failed-to-check-if-key-s-exists-from-bucket-s","errorCode":null,"errorMessage":"failed to check if key %s exists from bucket %s: %w","messagePattern":"failed to check if key (.+?) exists from bucket (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"workflow/artifacts/s3/s3.go","lineNumber":406,"sourceCode":"\treturn files, err\n}\n\n// listObjects returns the files inside the directory represented by the Artifact\n// returns true if success or can't be retried (non-transient error)\n// returns false if it can be retried (transient error)\nfunc listObjects(ctx context.Context, s3cli Client, artifact *wfv1.Artifact) (bool, []string, error) {\n\tvar files []string\n\tfiles, err := s3cli.ListDirectory(artifact.S3.Bucket, artifact.S3.Key)\n\tif err != nil {\n\t\treturn !isTransientS3Err(ctx, err), files, fmt.Errorf(\"failed to list directory: %w\", err)\n\t}\n\tlog := logging.RequireLoggerFromContext(ctx)\n\tlog.WithFields(logging.Fields{\"bucket\": artifact.S3.Bucket, \"key\": artifact.S3.Key, \"files\": files}).Debug(ctx, \"successfully listing S3 directory\")\n\n\tif len(files) == 0 {\n\t\tdirectoryExists, err := s3cli.KeyExists(artifact.S3.Bucket, artifact.S3.Key)\n\t\tif err != nil {\n\t\t\treturn !isTransientS3Err(ctx, err), files, fmt.Errorf(\"failed to check if key %s exists from bucket %s: %w\", artifact.S3.Key, artifact.S3.Bucket, err)\n\t\t}\n\t\tif !directoryExists {\n\t\t\treturn true, files, argoerrs.New(argoerrs.CodeNotFound, fmt.Sprintf(\"no key found of name %s\", artifact.S3.Key))\n\t\t}\n\t}\n\treturn true, files, nil\n}\n\nfunc (s3Driver *ArtifactDriver) IsDirectory(ctx context.Context, artifact *wfv1.Artifact) (bool, error) {\n\ts3cli, err := s3Driver.newClient(ctx)\n\tif err != nil {\n\t\treturn false, err\n\t}\n\treturn s3cli.IsDirectory(artifact.S3.Bucket, artifact.S3.Key)\n}\n\n// Get AWS credentials based on default order from aws SDK\nfunc getAWSCredentials(ctx context.Context, opts ClientOpts) (*credentials.Credentials, error) {","sourceCodeStart":388,"sourceCodeEnd":424,"githubUrl":"https://github.com/argoproj/argo-workflows/blob/35bff19146f5a6ada77468c431f2624bd577e373/workflow/artifacts/s3/s3.go#L388-L424","documentation":"Wraps a failure from s3cli.KeyExists when listObjects finds no files under the artifact key and double-checks whether the key itself exists. The KeyExists S3 API call itself errored (as opposed to returning false), so load cannot distinguish missing vs broken; transient errors are retried.","triggerScenarios":"After ListDirectory returns an empty file list, listObjects calls s3cli.KeyExists(bucket, key) which fails: AccessDenied on HeadObject, throttling, network error.","commonSituations":"IAM policy permits ListBucket but denies GetObject/HeadObject; aggressive S3 rate limiting; intermittent connectivity to the endpoint.","solutions":["Check the wrapped cause (often HeadObject AccessDenied or throttling)","Ensure credentials allow s3:GetObject/HeadObject on the key prefix","Retry the workflow if the cause is transient throttling — the executor backoff should eventually succeed","Verify endpoint/TLS configuration if errors are connection-level"],"exampleFix":"// before (IAM)\n// only s3:ListBucket granted\n// after\n{\"Effect\":\"Allow\",\"Action\":[\"s3:ListBucket\",\"s3:GetObject\"],\"Resource\":[\"arn:aws:s3:::my-bucket\",\"arn:aws:s3:::my-bucket/*\"]}","handlingStrategy":"retry","validationCode":"aws --endpoint-url $ENDPOINT s3api head-object --bucket $BUCKET --key $KEY || aws s3api head-bucket --bucket $BUCKET","typeGuard":null,"tryCatchPattern":"// treat as possibly-transient: rely on executor backoff; surface cause\nif unwrapped := errors.Unwrap(err); unwrapped != nil { log.Printf(\"KeyExists check failed: %v\", unwrapped) }","preventionTips":["Ensure IAM includes GetObject/HeadObject, not just ListBucket","Use bucket-versioned or idempotent artifact keys to reduce throttle pressure","Retry workflows on throttling errors; consider request-rate limits on the bucket"],"tags":["s3","artifacts","permissions","network"],"backgroundTag":"s3-key-exists-check-failed","analyzedSha":"35bff19146f5a6ada77468c431f2624bd577e373","analyzedAt":"2026-09-03T19:34:35.908Z","contentChangedAt":"2026-09-03T19:34:35.908Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}