argoproj/argo-workflows · error
plugin %s load failed: %w
Error message
plugin %s load failed: %w
What it means
Driver.Load calls the plugin's LoadArtifact RPC. This error wraps a transport/RPC-level failure (gRPC status error, connection dropped, context deadline) — the call itself failed rather than the plugin reporting a business-logic failure.
Source
Thrown at workflow/artifacts/plugin/plugin.go:154
}
// Close closes the gRPC connection
func (d *Driver) Close() error {
if d.conn != nil {
return d.conn.Close()
}
return nil
}
// Load implements ArtifactDriver.Load by calling the plugin service
func (d *Driver) Load(ctx context.Context, inputArtifact *wfv1.Artifact, path string) error {
grpcArtifact := convertToGRPC(inputArtifact)
resp, err := d.client.Load(ctx, &artifact.LoadArtifactRequest{
InputArtifact: grpcArtifact,
Path: path,
})
if err != nil {
return fmt.Errorf("plugin %s load failed: %w", d.pluginName, err)
}
if !resp.Success {
return fmt.Errorf("plugin %s load failed: %s", d.pluginName, resp.Error)
}
return nil
}
// OpenStream implements ArtifactDriver.OpenStream by calling the plugin service
func (d *Driver) OpenStream(ctx context.Context, a *wfv1.Artifact) (io.ReadCloser, error) {
grpcArtifact := convertToGRPC(a)
stream, err := d.client.OpenStream(ctx, &artifact.OpenStreamRequest{
Artifact: grpcArtifact,
})
if err != nil {
return nil, fmt.Errorf("plugin %s open stream failed: %w", d.pluginName, err)
}
reader, writer := io.Pipe()View on GitHub (pinned to 35bff19146)
Solutions
- Check plugin pod stability (restarts, OOMKills) with kubectl get pod / describe
- Use errors.Is / status.Code(err) on the wrapped error to branch: retry Unavailable/DeadlineExceeded with backoff, fail fast on Unimplemented
- Increase the context/step timeout for large artifact loads
- Upgrade the plugin to match the controller's artifact gRPC API version
Example fix
// before: treat any failure as fatal
return d.Load(ctx, art, path)
// after: retry transient gRPC failures
err := d.Load(ctx, art, path)
if status.Code(err) == codes.Unavailable {
return retryWithBackoff(func() error { return d.Load(ctx, art, path) })
}
return err Defensive patterns
Strategy: retry
Validate before calling
// preflight the plugin before the artifact step
resp, err := drv.ListObjects(ctx, artifactRef)
if err != nil { return fmt.Errorf("plugin unreachable for artifact load: %w", err) } Try / catch
err := drv.Load(ctx, art, path)
if err != nil {
switch status.Code(err) {
case codes.Unavailable, codes.DeadlineExceeded, codes.Canceled:
return retryWithBackoff(3, func() error { return drv.Load(ctx, art, path) })
case codes.Unimplemented:
return fmt.Errorf("plugin too old for Load RPC: %w", err)
default:
return err
}
} Prevention
- Configure PodDisruptionBudgets/restart policies so plugins don't vanish mid-workflow
- Give artifact steps generous deadlines relative to artifact size
- Keep plugin and controller gRPC API versions in lockstep
When it happens
Trigger: The Load RPC returns a gRPC error: Unavailable (plugin restarted mid-workflow), DeadlineExceeded (ctx timeout during a large copy), Canceled (workflow/node cancelled), Unimplemented (plugin predates the Load RPC), or the connection broke mid-call.
Common situations: Plugin pod OOM-killed or restarted while an artifact was being loaded, network/context timeouts on large artifacts, plugin version older than the controller expecting a newer RPC surface.
Related errors
- plugin %s open stream failed: %w
- failed to dial plugin %s at %q: %w
- plugin %s connection shutdown (socket=%q)
- timeout waiting for plugin %s connection to become ready, la
- plugin %s load failed: %s
AI-assisted analysis of argoproj/argo-workflows@35bff19146 (2026-09-03).
Data as JSON: /api/errors/3b85be7925c60714.
Report an issue: GitHub.