{"record":{"id":"ba8df6df0c4b19f3","repo":"argoproj/argo-workflows","slug":"plugin-s-list-objects-failed-w","errorCode":null,"errorMessage":"plugin %s list objects failed: %w","messagePattern":"plugin (.+?) list objects failed: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"workflow/artifacts/plugin/plugin.go","lineNumber":348,"sourceCode":"\t\tArtifact: grpcArtifact,\n\t})\n\tif err != nil {\n\t\treturn fmt.Errorf(\"plugin %s delete failed: %w\", d.pluginName, err)\n\t}\n\tif !resp.Success {\n\t\treturn fmt.Errorf(\"plugin %s delete failed: %s\", d.pluginName, resp.Error)\n\t}\n\treturn nil\n}\n\n// ListObjects implements ArtifactDriver.ListObjects by calling the plugin service\nfunc (d *Driver) ListObjects(ctx context.Context, artifactRef *wfv1.Artifact) ([]string, error) {\n\tgrpcArtifact := convertToGRPC(artifactRef)\n\tresp, err := d.client.ListObjects(ctx, &artifact.ListObjectsRequest{\n\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)","sourceCodeStart":330,"sourceCodeEnd":366,"githubUrl":"https://github.com/argoproj/argo-workflows/blob/35bff19146f5a6ada77468c431f2624bd577e373/workflow/artifacts/plugin/plugin.go#L330-L366","documentation":"Driver.ListObjects calls the plugin's ListObjects RPC to enumerate artifact keys. If the gRPC call itself fails (transport error, deadline, unimplemented, invalid request), the driver wraps it as \"plugin %s list objects failed: %w\" and returns no objects. The plugin's own logical error string is handled separately (error 514).","triggerScenarios":"Calling Driver.ListObjects(ctx, artifactRef) when the RPC returns a gRPC error: plugin not running (Unavailable), plugin binary lacks ListObjects (Unimplemented), ctx deadline exceeded while listing a huge prefix, or InvalidArgument from a malformed artifact ref (empty/unset key prefix).","commonSituations":"Archived workflow log/artifact listing against a plugin that was restarted; old plugin image missing ListObjects; very large buckets causing deadline exceeded; artifact ref key left empty by a template bug so the request is invalid.","solutions":["Unwrap the %w gRPC status: Unavailable → restart/fix the plugin; Unimplemented → upgrade the plugin to one that implements ListObjects.","Validate the artifact reference key/prefix before calling so the request isn't InvalidArgument.","Increase the context timeout or narrow the listed prefix if deadline exceeded on large listings.","Check plugin logs for server-side errors (auth failure to backend, throttling)."],"exampleFix":"// validating the ref before listing\n// before:\nobjs, err := driver.ListObjects(ctx, art) // art.Key == \"\"\n// after:\nif art.Key == \"\" {\n\treturn fmt.Errorf(\"artifact key required for ListObjects\")\n}\nobjs, err := driver.ListObjects(ctx, art)","handlingStrategy":"validation","validationCode":"// validate request inputs before calling ListObjects\nfunc validateListRef(a *wfv1.Artifact) error {\n\tif a == nil {\n\t\treturn errors.New(\"nil artifact ref\")\n\t}\n\tif a.GetKey() == \"\" {\n\t\treturn errors.New(\"artifact key/prefix required for ListObjects\")\n\t}\n\tif ctx.Err() != nil {\n\t\treturn ctx.Err()\n\t}\n\treturn nil\n}","typeGuard":"func isUnimplementedList(err error) bool {\n\treturn status.Code(err) == codes.Unimplemented // plugin binary lacks ListObjects\n}","tryCatchPattern":"objs, err := driver.ListObjects(ctx, art)\nif err != nil {\n\tif isUnimplementedList(err) {\n\t\treturn nil, fmt.Errorf(\"plugin %s too old for listing; upgrade plugin image\", pluginName)\n\t}\n\tif status.Code(err) == codes.DeadlineExceeded {\n\t\tctx2, cancel := context.WithTimeout(context.Background(), 5*time.Minute)\n\t\tdefer cancel()\n\t\treturn driver.ListObjects(ctx2, art) // retry with larger budget\n\t}\n\treturn nil, err\n}","preventionTips":["Upgrade plugin images whenever the controller gains new RPCs (ListObjects, SaveStream, GetCapabilities).","Set timeouts proportional to expected listing size; narrow prefixes for large buckets.","Always populate the artifact key/prefix in templates before listing.","Health-check the plugin endpoint before batch listing operations."],"tags":["grpc","plugin","artifacts","list"],"backgroundTag":"grpc-rpc-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"}