argoproj/argo-workflows · error
plugin %s save failed: %s
Error message
plugin %s save failed: %s
What it means
This variant fires when the plugin's Save RPC completed successfully at the gRPC level but the response reports Success=false with an application-level Error string. The error message contains the plugin's own error text after 'save failed: ', so it is plugin-side business logic failure (e.g. it could not write to the destination), not a transport problem.
Source
Thrown at workflow/artifacts/plugin/plugin.go:215
}
}
}()
return reader, nil
}
// Save implements ArtifactDriver.Save by calling the plugin service
func (d *Driver) Save(ctx context.Context, path string, outputArtifact *wfv1.Artifact) error {
grpcArtifact := convertToGRPC(outputArtifact)
resp, err := d.client.Save(ctx, &artifact.SaveArtifactRequest{
Path: path,
OutputArtifact: grpcArtifact,
})
if err != nil {
return fmt.Errorf("plugin %s save failed: %w", d.pluginName, err)
}
if !resp.Success {
return fmt.Errorf("plugin %s save failed: %s", d.pluginName, resp.Error)
}
return nil
}
// saveStreamChunkSize is the size of each chunk sent over the streaming SaveStream RPC.
// 2MiB stays well under gRPC's default 4MiB max message size while keeping the
// per-chunk marshal/syscall overhead low for multi-GB artifacts.
const saveStreamChunkSize = 2 * 1024 * 1024
// SaveStream implements ArtifactDriver.SaveStream. If the plugin advertises
// streaming support (per GetCapabilities), the reader is streamed directly with no
// local buffering. Otherwise it falls back to buffering to a temp file and calling
// the existing unary Save, so a plugin that predates streaming keeps working.
//
// Capability is checked before reader is touched: once GetCapabilities confirms
// streaming support and chunks start being sent, a mid-stream failure is returned
// as an error rather than retried via the fallback, since the reader may already be
// partially consumed and cannot be rewound.View on GitHub (pinned to 35bff19146)
Solutions
- Read the message after 'plugin <name> save failed: ' — it is the plugin's own error string explaining the failure
- Check the plugin's logs for the full stack trace behind that error
- Verify destination storage credentials, bucket existence, and write permissions from the plugin pod
- Fix the artifact spec (path, key, flags) if the plugin rejected it as invalid
Defensive patterns
Strategy: validation
Validate before calling
// Validate the artifact spec and destination before calling Save:
if artifact.ArtifactLocation == nil || artifact.S3 == nil && artifact.GCS == nil {
return fmt.Errorf("artifact has no plugin-supported location configured")
}
if path == "" {
return fmt.Errorf("artifact save path is empty")
} Type guard
func isPluginAppError(err error) (string, bool) {
s := err.Error()
if strings.Contains(s, "save failed: ") && !errors.Is(err, nil) {
idx := strings.LastIndex(s, "save failed: ")
return s[idx+len("save failed: "):], true
}
return "", false
} Try / catch
if err := driver.Save(ctx, path, artifact); err != nil {
if msg, ok := isPluginAppError(err); ok {
logger.Error("plugin rejected save", "reason", msg)
// fix artifact config/credentials; do NOT blind-retry
}
return err
} Prevention
- Read the plugin's error string — it names the exact rejection cause
- Validate destination bucket/prefix existence and plugin credentials ahead of runs
- Keep plugin storage config in a checked-in, reviewed configmap
- Dry-run the plugin's save with a test artifact after config changes
When it happens
Trigger: Calling Driver.Save and receiving resp.Success == false — the plugin processed the request but failed internally and returned its error in-band in resp.Error.
Common situations: Plugin cannot authenticate to object storage, destination bucket/prefix does not exist or is not writable, size/quota limits hit on the backend, plugin rejected the artifact path or metadata.
Related errors
- plugin %s save failed: %w
- plugin %s save stream failed: %s
- failed to create plugin driver for %s: %w
- plugin %s stream error: %s
- plugin %s save stream failed to open: %w
AI-assisted analysis of argoproj/argo-workflows@35bff19146 (2026-09-03).
Data as JSON: /api/errors/e010bbca0167bd16.
Report an issue: GitHub.