{"record":{"id":"654e45a53136bc19","repo":"argoproj/argo-workflows","slug":"plugin-s-is-directory-check-failed-w","errorCode":null,"errorMessage":"plugin %s is directory check failed: %w","messagePattern":"plugin (.+?) is directory check failed: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"workflow/artifacts/plugin/plugin.go","lineNumber":363,"sourceCode":"\t\tArtifact: grpcArtifact,\n\t})\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"plugin %s list objects failed: %w\", d.pluginName, err)\n\t}\n\tif resp.Error != \"\" {\n\t\treturn nil, fmt.Errorf(\"plugin %s list objects failed: %s\", d.pluginName, resp.Error)\n\t}\n\treturn resp.Objects, nil\n}\n\n// IsDirectory implements ArtifactDriver.IsDirectory by calling the plugin service\nfunc (d *Driver) IsDirectory(ctx context.Context, artifactRef *wfv1.Artifact) (bool, error) {\n\tgrpcArtifact := convertToGRPC(artifactRef)\n\tresp, err := d.client.IsDirectory(ctx, &artifact.IsDirectoryRequest{\n\t\tArtifact: grpcArtifact,\n\t})\n\tif err != nil {\n\t\treturn false, fmt.Errorf(\"plugin %s is directory check failed: %w\", d.pluginName, err)\n\t}\n\tif resp.Error != \"\" {\n\t\treturn false, fmt.Errorf(\"plugin %s is directory check failed: %s\", d.pluginName, resp.Error)\n\t}\n\treturn resp.IsDirectory, nil\n}\n\n// convertToGRPC converts v1alpha1.Artifact to gRPC Artifact\nfunc convertToGRPC(a *wfv1.Artifact) *artifact.Artifact {\n\tif a == nil {\n\t\treturn nil\n\t}\n\n\tgrpcArtifact := &artifact.Artifact{\n\t\tName:           a.Name,\n\t\tPath:           a.Path,\n\t\tFrom:           a.From,\n\t\tOptional:       a.Optional,","sourceCodeStart":345,"sourceCodeEnd":381,"githubUrl":"https://github.com/argoproj/argo-workflows/blob/35bff19146f5a6ada77468c431f2624bd577e373/workflow/artifacts/plugin/plugin.go#L345-L381","documentation":"This error wraps a transport-level failure from the gRPC IsDirectory call made by the plugin artifact driver. Argo Workflows artifact plugins run as external gRPC servers; the driver delegates the directory check to the plugin and wraps any RPC error with the plugin name for context. It means the plugin could not be reached or the RPC failed, not that the artifact is or isn't a directory.","triggerScenarios":"Calling Driver.IsDirectory on a plugin artifact when the plugin gRPC server is unreachable, crashed, timed out, returned a connection error, or the plugin socket/address configured via the plugin artifact is wrong.","commonSituations":"Plugin container not running or still starting when the workflow checks artifacts (ArtificialFailedNode / artifact GC / artifact passing); misconfigured artifact plugin address; plugin crashing mid-request; network policy blocking the plugin port; TLS or auth mismatch between argoexec/controller and the plugin.","solutions":["Check the plugin pod/server is running and healthy (kubectl get pods, plugin logs) and restart it if crashed","Verify the artifact plugin address/socket in the artifact plugin configuration matches the running plugin's endpoint","Test connectivity from the controller/argoexec network path to the plugin (network policies, service ports)","Inspect the wrapped inner error (%w chain) for the root cause — DNS, connection refused, deadline exceeded — and fix that directly","If the plugin is slow, increase RPC timeout/retry settings or ensure plugin starts before workflows depend on it"],"exampleFix":"# before: plugin configured with wrong address\nartifactRepository:\n  plugin:\n    name: my-plugin\n    address: my-plugin:2746\n# after: correct service address/port in the same namespace\nartifactRepository:\n  plugin:\n    name: my-plugin\n    address: my-plugin.artifact-plugins.svc:2746","handlingStrategy":"try-catch","validationCode":"// before relying on plugin artifacts, verify the plugin gRPC endpoint is reachable\nconn, err := grpc.Dial(pluginAddress, grpc.WithBlock(), grpc.WithTimeout(5*time.Second))\nif err != nil {\n    return fmt.Errorf(\"artifact plugin %s unreachable: %w\", pluginName, err)\n}\nconn.Close()","typeGuard":null,"tryCatchPattern":"ok, err := driver.IsDirectory(ctx, artifact)\nif err != nil {\n    var se *status.Status // gRPC status is wrapped via %w\n    if errors.As(err, &se) && se.Code() == codes.Unavailable {\n        // retry after checking plugin pod health\n    }\n    return fmt.Errorf(\"is-directory check failed for plugin: %w\", err)\n}","preventionTips":["Add readiness/liveness probes to plugin pods so they are ready before workflows run","Pin the plugin service address and port in artifact configuration and validate with a startup check","Monitor plugin pod restarts/crash loops","Keep plugin TLS/auth configuration in sync with the controller/argoexec side"],"tags":["grpc","plugin","artifact","network"],"backgroundTag":"grpc-unavailable","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"}