hashicorp/terraform · error
wrapped err: %w
Error message
wrapped err: %w
What it means
Returned by WriteStateBytes (internal/grpcwrap/provider6.go:1075) when the bidirectional stream's srv.Recv() returns an error other than io.EOF while reading chunked state-upload messages. The error is wrapped with %w and stored in grpcErr, then returned after the receive loop breaks. The underlying cause is a transport-level stream failure (connection reset, cancellation, deadline, broken pipe).
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 c9def3e214)
Solutions
- Inspect the wrapped error (errors.Unwrap) to distinguish context cancellation from a transport error.
- Retry the operation: state writes are retried by Terraform core; ensure the network/state store is healthy.
- Increase gRPC keepalive/timeout allowances if uploads are large and slow.
- Check state store backend availability and that the connection is not behind an aggressive proxy.
Example fix
// before
for {
chunk, err := srv.Recv()
if err == io.EOF { break }
if err != nil {
grpcErr = fmt.Errorf("wrapped err: %w", err) // connection reset by peer
break
}
}
// after (caller side: retry on transient transport error)
if errors.Is(err, context.Canceled) || isTransient(err) {
// retry the state upload
} Defensive patterns
Strategy: retry
Validate before calling
// Before uploading, verify the stream/context is alive:
func streamAlive(ctx context.Context) bool {
return ctx.Err() == nil
} Type guard
func isTransientRecvErr(err error) bool {
return errors.Is(err, context.Canceled) ||
errors.Is(err, context.DeadlineExceeded) ||
status.Code(err) == codes.Unavailable
} Try / catch
// Retry the whole WriteStateBytes upload on transient transport errors:
var lastErr error
for attempt := 0; attempt < 3; attempt++ {
err := uploadState(ctx, bytes)
if err == nil { return nil }
lastErr = err
if !isTransientRecvErr(err) { break }
}
return lastErr Prevention
- Size gRPC keepalive/timeouts to the largest expected state upload.
- Retry idempotent state writes on transient transport errors.
- Distinguish context.Canceled (user) from real network failures.
- Avoid aggressive proxies that close idle streaming connections.
When it happens
Trigger: During a state-store upload over the WriteStateBytes server-streaming RPC, the client (Terraform core) drops the connection, the gRPC context is cancelled, or the network link breaks mid-stream; srv.Recv() then returns a non-EOF error and it is wrapped here.
Common situations: Unstable network to a remote state store, gRPC keepalive/timeout killing a long upload, context cancellation (e.g. user Ctrl-C during apply), state store backend restart mid-write, or proxy/load-balancer closing idle streams.
Related errors
- error writing state: %w
- failed to send completed event: %w
- expected to receive state in %d bytes, actually received %d
- Failed to read state file from %v: %v
- Failed to read remote state: %s
AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07).
Data as JSON: /api/errors/c1bd29087ba3a114.
Report an issue: GitHub.