hashicorp/terraform · error
wrapped err
Error message
wrapped err: %w
What it means
Returned (after the receive loop) by the tfplugin6 WriteStateBytes handler when srv.Recv() returned an error other than io.EOF. The error is captured into grpcErr, the loop breaks, and grpcErr is returned once the loop exits. The %w carries the underlying gRPC stream error.
Solutions
- Inspect status.Code(err) on the wrapped value: Canceled/DeadlineExceeded imply interruption, ResourceExhausted implies message size, Unavailable implies transport.
- Retry the state write once the underlying condition clears.
- Ensure each chunk stays within the configured gRPC max message size.
- Confirm the client remains connected for the entire streaming write.
- Check provider/core logs for the upstream cancellation cause.
Example fix
// before
chunk, err := srv.Recv()
if err != nil && err != io.EOF {
grpcErr = fmt.Errorf("wrapped err: %w", err)
}
// after: surface the status code for diagnosability
if err != nil && err != io.EOF {
grpcErr = status.Errorf(status.Code(err), "receiving state chunk: %v", err)
} Defensive patterns
Strategy: try-catch
Try / catch
// Handle a mid-stream receive failure on WriteStateBytes.
err := client.WriteStateBytes(ctx, chunks)
if err != nil {
st, ok := status.FromError(err)
switch {
case !ok:
return err // non-gRPC error
case st.Code() == codes.Canceled || st.Code() == codes.DeadlineExceeded:
return fmt.Errorf("state write interrupted: %v", err) // do not blindly retry
case st.Code() == codes.ResourceExhausted:
return fmt.Errorf("state chunk exceeded max message size: %v", err)
case st.Code() == codes.Unavailable:
return retryableErr(err) // safe to retry after reconnect
}
} Prevention
- Keep each chunk under the configured gRPC max receive/send message size.
- Hold the context open for the entire streaming write.
- Retry only on Unavailable; treat Canceled as intentional interruption.
When it happens
Trigger: srv.Recv() inside the WriteStateBytes streaming loop returns a non-nil, non-io.EOF error: client disconnect, context cancellation, transport failure, or message-size-limit exceeded.
Common situations: State upload interrupted by the user; network drop between core and provider; context deadline; oversized chunk beyond gRPC max receive message size.
Related errors
- failed to send completed event
- error writing state
- expected to receive state in
- Error downloading state
- Error retrieving state
AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11).
Data as JSON: /api/errors/c1bd29087ba3a114.
Report an issue: GitHub.
Appendix: source
Thrown at internal/grpcwrap/provider6.go:1075
rangeStart += byteCount
}
}
func (p *provider6) WriteStateBytes(srv tfplugin6.Provider_WriteStateBytesServer) error {
var typeName string
var stateId string
state := bytes.Buffer{}
var grpcErr error
var totalReceivedBytes int
var expectedTotalLength int64
for {
chunk, err := srv.Recv()
if err == io.EOF {
break
}
if err != nil {
grpcErr = fmt.Errorf("wrapped err: %w", err)
break
}
if expectedTotalLength == 0 {
// On the first iteration
expectedTotalLength = chunk.TotalLength // record expected length
if chunk.Meta != nil {
// We expect the Meta to be set on the first message, only
typeName = chunk.Meta.TypeName
stateId = chunk.Meta.StateId
} else {
panic("expected Meta to be set on first chunk sent to WriteStateBytes")
}
}
n, err := state.Write(chunk.Bytes)
if err != nil {
return fmt.Errorf("error writing state: %w", err)
}View on GitHub (pinned to d32a084675)