{"record":{"id":"9d9b0d184e8582e0","repo":"argoproj/argo-workflows","slug":"plugin-s-open-stream-failed-w","errorCode":null,"errorMessage":"plugin %s open stream failed: %w","messagePattern":"plugin (.+?) open stream failed: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"workflow/artifacts/plugin/plugin.go","lineNumber":169,"sourceCode":"\t\tPath:          path,\n\t})\n\tif err != nil {\n\t\treturn fmt.Errorf(\"plugin %s load failed: %w\", d.pluginName, err)\n\t}\n\tif !resp.Success {\n\t\treturn fmt.Errorf(\"plugin %s load failed: %s\", d.pluginName, resp.Error)\n\t}\n\treturn nil\n}\n\n// OpenStream implements ArtifactDriver.OpenStream by calling the plugin service\nfunc (d *Driver) OpenStream(ctx context.Context, a *wfv1.Artifact) (io.ReadCloser, error) {\n\tgrpcArtifact := convertToGRPC(a)\n\tstream, err := d.client.OpenStream(ctx, &artifact.OpenStreamRequest{\n\t\tArtifact: grpcArtifact,\n\t})\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"plugin %s open stream failed: %w\", d.pluginName, err)\n\t}\n\n\treader, writer := io.Pipe()\n\n\tgo func() {\n\t\tdefer writer.Close()\n\t\tfor {\n\t\t\tresp, err := stream.Recv()\n\t\t\tif errors.Is(err, io.EOF) {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tif err != nil {\n\t\t\t\twriter.CloseWithError(fmt.Errorf(\"plugin %s stream receive failed: %w\", d.pluginName, err))\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif resp.Error != \"\" {\n\t\t\t\twriter.CloseWithError(fmt.Errorf(\"plugin %s stream error: %s\", d.pluginName, resp.Error))\n\t\t\t\treturn","sourceCodeStart":151,"sourceCodeEnd":187,"githubUrl":"https://github.com/argoproj/argo-workflows/blob/35bff19146f5a6ada77468c431f2624bd577e373/workflow/artifacts/plugin/plugin.go#L151-L187","documentation":"Driver.OpenStream calls the plugin's OpenStream RPC to get a server-stream of artifact bytes. This error wraps a failure establishing the stream (gRPC status error, connection dropped, context done) — no byte stream was created, so the caller receives nil reader.","triggerScenarios":"OpenStream RPC fails at call time: plugin Unavailable (restarting), DeadlineExceeded, Canceled context, Unimplemented (old plugin without OpenStream), or message-size/auth failures on the request.","commonSituations":"Streaming an artifact (e.g. to logs or another artifact) right when the plugin pod restarts; using an older plugin build lacking the streaming API; short ctx deadlines on large artifacts.","solutions":["Check plugin pod health and restart the workflow step if Unavailable","Inspect status.Code(err) on the wrapped error to distinguish transient vs permanent causes","Upgrade the plugin if it does not implement OpenStream (Unimplemented)","Raise the context timeout / connectionTimeoutSeconds for large streams"],"exampleFix":"// before\nrc, err := driver.OpenStream(ctx, a)\n// after\ncode := status.Code(err)\nif code == codes.Unavailable || code == codes.DeadlineExceeded {\n    rc, err = driver.OpenStream(ctx, a) // retry once with fresh ctx\n}\nif err != nil { return nil, fmt.Errorf(\"open stream: %w\", err) }","handlingStrategy":"retry","validationCode":"// verify plugin readiness before opening streams\nif err := drv.ping(ctx); err != nil { // e.g. GetCapabilities probe\n    return fmt.Errorf(\"plugin not ready for streaming: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"rc, err := drv.OpenStream(ctx, a)\nif err != nil {\n    if c := status.Code(err); c == codes.Unavailable || c == codes.DeadlineExceeded {\n        return retryWithBackoff(func() (io.ReadCloser, error) { return drv.OpenStream(ctx, a) })\n    }\n    if c == codes.Unimplemented {\n        return fallbackToUnaryLoad(ctx, a) // old plugin without OpenStream\n    }\n    return nil, err\n}","preventionTips":["Upgrade plugins to builds that implement OpenStream if you rely on streaming","Keep artifact-streaming contexts alive long enough for the full transfer","Monitor plugin pod restarts; they are the top cause of Unavailable on stream open"],"tags":["grpc","streaming","rpc-error","plugin-driver"],"backgroundTag":"grpc-stream-open-failed","analyzedSha":"35bff19146f5a6ada77468c431f2624bd577e373","analyzedAt":"2026-09-03T19:34:35.908Z","contentChangedAt":"2026-09-03T19:34:35.908Z","schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}