argoproj/argo-workflows · error
plugin %s list objects failed: %w
Error message
plugin %s list objects failed: %w
What it means
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).
Source
Thrown at workflow/artifacts/plugin/plugin.go:348
Artifact: grpcArtifact,
})
if err != nil {
return fmt.Errorf("plugin %s delete failed: %w", d.pluginName, err)
}
if !resp.Success {
return fmt.Errorf("plugin %s delete failed: %s", d.pluginName, resp.Error)
}
return nil
}
// ListObjects implements ArtifactDriver.ListObjects by calling the plugin service
func (d *Driver) ListObjects(ctx context.Context, artifactRef *wfv1.Artifact) ([]string, error) {
grpcArtifact := convertToGRPC(artifactRef)
resp, err := d.client.ListObjects(ctx, &artifact.ListObjectsRequest{
Artifact: grpcArtifact,
})
if err != nil {
return nil, fmt.Errorf("plugin %s list objects failed: %w", d.pluginName, err)
}
if resp.Error != "" {
return nil, fmt.Errorf("plugin %s list objects failed: %s", d.pluginName, resp.Error)
}
return resp.Objects, nil
}
// IsDirectory implements ArtifactDriver.IsDirectory by calling the plugin service
func (d *Driver) IsDirectory(ctx context.Context, artifactRef *wfv1.Artifact) (bool, error) {
grpcArtifact := convertToGRPC(artifactRef)
resp, err := d.client.IsDirectory(ctx, &artifact.IsDirectoryRequest{
Artifact: grpcArtifact,
})
if err != nil {
return false, fmt.Errorf("plugin %s is directory check failed: %w", d.pluginName, err)
}
if resp.Error != "" {
return false, fmt.Errorf("plugin %s is directory check failed: %s", d.pluginName, resp.Error)View on GitHub (pinned to 35bff19146)
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).
Example fix
// validating the ref before listing
// before:
objs, err := driver.ListObjects(ctx, art) // art.Key == ""
// after:
if art.Key == "" {
return fmt.Errorf("artifact key required for ListObjects")
}
objs, err := driver.ListObjects(ctx, art) Defensive patterns
Strategy: validation
Validate before calling
// validate request inputs before calling ListObjects
func validateListRef(a *wfv1.Artifact) error {
if a == nil {
return errors.New("nil artifact ref")
}
if a.GetKey() == "" {
return errors.New("artifact key/prefix required for ListObjects")
}
if ctx.Err() != nil {
return ctx.Err()
}
return nil
} Type guard
func isUnimplementedList(err error) bool {
return status.Code(err) == codes.Unimplemented // plugin binary lacks ListObjects
} Try / catch
objs, err := driver.ListObjects(ctx, art)
if err != nil {
if isUnimplementedList(err) {
return nil, fmt.Errorf("plugin %s too old for listing; upgrade plugin image", pluginName)
}
if status.Code(err) == codes.DeadlineExceeded {
ctx2, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
defer cancel()
return driver.ListObjects(ctx2, art) // retry with larger budget
}
return nil, err
} Prevention
- 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.
When it happens
Trigger: 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).
Common situations: 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.
Related errors
- plugin %s stream error: %s
- plugin %s save failed: %w
- plugin %s save stream failed to open: %w
- plugin %s save stream failed %s: %w
- plugin %s save stream failed: %w
AI-assisted analysis of argoproj/argo-workflows@35bff19146 (2026-09-03).
Data as JSON: /api/errors/ba8df6df0c4b19f3.
Report an issue: GitHub.