apache/beam · error
unexpected ResolveArtifactResponse to GetArtifact: %v
Error message
unexpected ResolveArtifactResponse to GetArtifact: %v
What it means
In the prism job server's reverse artifact retrieval service, GetArtifact requests are answered with a stream of ArtifactResponseWrapper messages. The code expects the wrapper for a GetArtifact call to carry GetArtifactResponse data chunks. If the SDK harness instead replies with a ResolveArtifactResponse (the answer to the other RPC type), the server logs and returns this error — the response type does not match the outstanding request.
Source
Thrown at sdks/go/pkg/beam/runners/prism/internal/jobservices/artifact.go:81
}
if in.GetIsLast() {
slog.Debug("GetArtifact finished",
slog.Group("dep",
slog.String("urn", dep.GetTypeUrn()),
slog.String("payload", string(dep.GetTypePayload()))),
slog.Int("bytesReceived", buf.Len()),
slog.String("rtype", fmt.Sprintf("%T", in.GetResponse())),
)
break
}
// Here's where we go through each environment's artifacts.
// We do nothing with them.
switch req := in.GetResponse().(type) {
case *jobpb.ArtifactResponseWrapper_GetArtifactResponse:
buf.Write(req.GetArtifactResponse.GetData())
case *jobpb.ArtifactResponseWrapper_ResolveArtifactResponse:
err := fmt.Errorf("unexpected ResolveArtifactResponse to GetArtifact: %v", in.GetResponse())
slog.Error("GetArtifact failure", slog.Any("error", err))
return err
}
}
if len(s.artifacts) == 0 {
s.artifacts = map[string][]byte{}
}
s.artifacts[string(dep.GetTypePayload())] = buf.Bytes()
}
}
return nil
}
func (s *Server) ResolveArtifacts(_ context.Context, req *jobpb.ResolveArtifactsRequest) (*jobpb.ResolveArtifactsResponse, error) {
return &jobpb.ResolveArtifactsResponse{
Replacements: req.GetArtifacts(),
}, nil
}View on GitHub (pinned to 12126d8942)
Solutions
- Align the SDK harness and prism job server versions so artifact RPC responses match request types.
- Check the worker's artifact retrieval implementation — it must answer GetArtifact requests with GetArtifactResponse chunks.
- Capture job logs to see which artifact triggered the mismatch and reproduce with that artifact's staging.
Defensive patterns
Strategy: try-catch
Validate before calling
// Client-side: ensure GetArtifact is answered with GetArtifactResponse wrappers
if _, ok := wrapper.Response.(*jobpb.ArtifactResponseWrapper_GetArtifactResponse); !ok {
return fmt.Errorf("wrong response type for GetArtifact: %T", wrapper.Response)
} Type guard
// Go type guard on the streamed response
func isGetArtifactResponse(w *jobpb.ArtifactResponseWrapper) bool {
_, ok := w.GetResponse().(*jobpb.ArtifactResponseWrapper_GetArtifactResponse)
return ok
} Try / catch
err := streamArtifact(ctx, req)
if err != nil && strings.Contains(err.Error(), "unexpected ResolveArtifactResponse") {
log.Fatalf("worker answered the wrong artifact RPC; check harness/server version skew: %v", err)
} Prevention
- Deploy matching versions of prism and the SDK harness
- Do not interleave ResolveArtifact handling into the GetArtifact stream
- Test artifact retrieval after any Beam version upgrade
When it happens
Trigger: A worker returning an ArtifactResponseWrapper_ResolveArtifactResponse in the stream opened by a GetArtifact request handled by ReverseArtifactRetrievalService.
Common situations: SDK harness/job-server protocol version skew (client answering the wrong RPC); buggy or custom artifact plugins on the worker side.
Related errors
- error creating local job server: %v
- unable to provide %v to worker
- failed to send chunks for %v; close error: %v
- failed to close stream for %v; response: %v
- chunk send failed
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/7e505e438799a384.
Report an issue: GitHub.