{"record":{"id":"168f3344b55347ec","repo":"argoproj/argo-workflows","slug":"failed-get-directory-w","errorCode":null,"errorMessage":"failed get directory: %w","messagePattern":"failed get directory: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"workflow/artifacts/oss/oss.go","lineNumber":169,"sourceCode":"\t\t\torigErr := bucket.GetObjectToFile(objectName, path)\n\t\t\tif origErr == nil {\n\t\t\t\treturn true, nil\n\t\t\t}\n\t\t\tif !IsOssErrCode(origErr, \"NoSuchKey\") {\n\t\t\t\treturn !isTransientOSSErr(ctx, origErr), fmt.Errorf(\"failed to get file: %w\", origErr)\n\t\t\t}\n\t\t\t// If we get here, the error was a NoSuchKey. The key might be a oss \"directory\"\n\t\t\tisDir, err := IsOssDirectory(bucket, objectName)\n\t\t\tif err != nil {\n\t\t\t\treturn !isTransientOSSErr(ctx, err), fmt.Errorf(\"failed to test if %s/%s is a directory: %w\", bucketName, objectName, err)\n\t\t\t}\n\t\t\tif !isDir {\n\t\t\t\t// It's neither a file, nor a directory. Return the original NoSuchKey error\n\t\t\t\treturn false, origErr\n\t\t\t}\n\n\t\t\tif err = GetOssDirectory(ctx, bucket, objectName, path); err != nil {\n\t\t\t\treturn !isTransientOSSErr(ctx, err), fmt.Errorf(\"failed get directory: %w\", err)\n\t\t\t}\n\t\t\treturn true, nil\n\t\t})\n\treturn err\n}\n\n// OpenStream opens a stream reader for an artifact from OSS compliant storage\nfunc (ossDriver *ArtifactDriver) OpenStream(ctx context.Context, inputArtifact *wfv1.Artifact) (io.ReadCloser, error) {\n\tvar stream io.ReadCloser\n\terr := waitutil.Backoff(defaultRetry,\n\t\tfunc() (bool, error) {\n\t\t\tlogging.RequireLoggerFromContext(ctx).WithField(\"key\", inputArtifact.OSS.Key).Info(ctx, \"OSS OpenStream\")\n\t\t\tosscli, err := ossDriver.newOSSClient(ctx)\n\t\t\tif err != nil {\n\t\t\t\treturn !isTransientOSSErr(ctx, err), err\n\t\t\t}\n\t\t\tbucketName := inputArtifact.OSS.Bucket\n\t\t\terr = setBucketLogging(osscli, bucketName)","sourceCodeStart":151,"sourceCodeEnd":187,"githubUrl":"https://github.com/argoproj/argo-workflows/blob/35bff19146f5a6ada77468c431f2624bd577e373/workflow/artifacts/oss/oss.go#L151-L187","documentation":"When the missing OSS key turns out to be a directory prefix, Load downloads the whole prefix via GetOssDirectory (recursively listing and fetching every object under it). Any failure inside that recursive download — a nested object 403/404, listing pagination failure, or local write error — is wrapped as 'failed get directory'.","triggerScenarios":"Artifact key references a folder-style prefix that exists in OSS, GetOssDirectory enumerates its objects, and one or more sub-operations fail: credentials can List but not Get some objects, an object disappears mid-download, or a local disk write fails on a large directory.","commonSituations":"Downloading folder outputs produced by a previous workflow step where the RAM policy only covers a subset of keys; huge directories exceeding disk space in the pod; concurrent modification of the prefix while downloading.","solutions":["Check the wrapped error for the failing object; grant GetObject on all keys under the prefix.","Verify the pod has enough disk space in the destination volume for the entire directory.","If only some files are needed, reference the specific object keys individually instead of the directory prefix.","Re-run the workflow if objects were concurrently deleted/overwritten mid-download."],"exampleFix":"// before: downloading whole prefix with partial permissions\noss:\n  bucket: b\n  key: outputs/\n// after: grant policy on prefix\n{ \"Action\": [\"oss:GetObject\"], \"Resource\": [\"acs:oss:*:*:b/outputs/*\"], \"Effect\": \"Allow\" }","handlingStrategy":"retry","validationCode":"// preflight: enumerate the prefix and verify overall size fits the destination volume\nb, _ := cli.Bucket(bucket)\nls, err := b.ListObjects(oss.Prefix(key))\nif err != nil {\n\treturn err\n}\nvar total int64\nfor _, o := range ls.Objects {\n\ttotal += o.Size\n}\n// compare total against available space on the target mount before Load","typeGuard":null,"tryCatchPattern":"err := driver.Load(ctx, art, path)\nif err != nil && strings.Contains(err.Error(), \"failed get directory\") {\n\t// recursive download failed mid-way; log wrapped cause, retry or shrink scope\n}","preventionTips":["Grant GetObject on every key under the prefix, not a subset","Provision enough disk in the destination volume for the whole directory","Avoid concurrent writers to the prefix during download","For large trees, split into several file artifacts instead of a folder"],"tags":["oss","artifact","directory","download","permissions"],"backgroundTag":"oss-directory-download-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"}