{"record":{"id":"45e2b2386cfa0799","repo":"hashicorp/terraform","slug":"expected-to-receive-state-in-d-bytes-actually-re","errorCode":null,"errorMessage":"expected to receive state in %d bytes, actually received %d bytes","messagePattern":"expected to receive state in (.+?) bytes, actually received (.+?) bytes","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/grpcwrap/provider6.go","lineNumber":1102,"sourceCode":"\t\t\t\tstateId = chunk.Meta.StateId\n\t\t\t} else {\n\t\t\t\tpanic(\"expected Meta to be set on first chunk sent to WriteStateBytes\")\n\t\t\t}\n\t\t}\n\n\t\tn, err := state.Write(chunk.Bytes)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"error writing state: %w\", err)\n\t\t}\n\t\ttotalReceivedBytes += n\n\t}\n\n\tif grpcErr != nil {\n\t\treturn grpcErr\n\t}\n\n\tif int64(totalReceivedBytes) != expectedTotalLength {\n\t\treturn fmt.Errorf(\"expected to receive state in %d bytes, actually received %d bytes\", expectedTotalLength, totalReceivedBytes)\n\t}\n\n\tif totalReceivedBytes == 0 {\n\t\t// Even an empty state file has content; no bytes is not valid\n\t\treturn errors.New(\"No state data received from Terraform: No state data was received from Terraform. This is a bug and should be reported.\")\n\t}\n\n\tresp := p.provider.WriteStateBytes(providers.WriteStateBytesRequest{\n\t\tStateId:  stateId,\n\t\tTypeName: typeName,\n\t\tBytes:    state.Bytes(),\n\t})\n\n\terr := srv.SendAndClose(&proto6.WriteStateBytes_Response{\n\t\tDiagnostics: convert.AppendProtoDiag([]*proto6.Diagnostic{}, resp.Diagnostics),\n\t})\n\n\treturn err","sourceCodeStart":1084,"sourceCodeEnd":1120,"githubUrl":"https://github.com/hashicorp/terraform/blob/c9def3e214014c1188faabfc4a5bde5095139765/internal/grpcwrap/provider6.go#L1084-L1120","documentation":"Returned by WriteStateBytes (internal/grpcwrap/provider6.go:1102) after the receive loop completes when the total bytes actually written (totalReceivedBytes) do not match the TotalLength the client declared in the first chunk (expectedTotalLength). The stream ended cleanly but the byte accounting is inconsistent, so the assembled buffer is rejected rather than persisted.","triggerScenarios":"A client that sets TotalLength=N on the first chunk but sends a different number of bytes total (chunk loss, duplicated/missed sends, client bug), or a transport that silently truncated the stream before EOF.","commonSituations":"Client-side chunking bug in Terraform core, a middleware/proxy that alters or drops chunks, retry logic that resends partial chunks, or a buggy state store wrapper miscalculating TotalLength.","solutions":["Check client/core version for known chunking bugs and upgrade if applicable.","Inspect for any proxy/gateway between core and the provider that could mutate or drop gRPC messages.","Capture a gRPC trace to compare bytes sent vs TotalLength declared.","If implementing a custom state store client, ensure TotalLength equals the sum of all chunk.Bytes lengths exactly."],"exampleFix":"// before (custom client)\nfirstChunk.TotalLength = 1024\n// but only 900 bytes of chunk.Bytes sent across all messages\n// -> expected to receive state in 1024 bytes, actually received 900 bytes\n\n// after\ntotal := int64(0)\nfor _, c := range chunks { total += int64(len(c.Bytes)) }\nchunks[0].TotalLength = total","handlingStrategy":"validation","validationCode":"// Client side: compute TotalLength exactly from the sum of chunk sizes:\nfunc buildChunks(full []byte, chunkSize int) []*tfplugin6.WriteStateBytes_Request {\n    total := int64(len(full))\n    var chunks []*tfplugin6.WriteStateBytes_Request\n    for i := 0; i < len(full); i += chunkSize {\n        end := i + chunkSize\n        if end > len(full) { end = len(full) }\n        chunks = append(chunks, &tfplugin6.WriteStateBytes_Request{\n            Bytes:       full[i:end],\n            TotalLength: total,\n        })\n    }\n    return chunks\n}","typeGuard":"func chunksConsistent(chunks []*tfplugin6.WriteStateBytes_Request) bool {\n    if len(chunks) == 0 { return true }\n    total := int64(0)\n    for _, c := range chunks { total += int64(len(c.Bytes)) }\n    return total == chunks[0].TotalLength\n}","tryCatchPattern":"if err := streamUpload(chunks); err != nil {\n    if strings.Contains(err.Error(), \"expected to receive state in\") {\n        // rebuild chunks with correct TotalLength and retry\n        chunks = buildChunks(full, chunkSize)\n    }\n}","preventionTips":["Set TotalLength to the exact sum of all chunk byte lengths.","Avoid proxies/middleware that alter gRPC message payloads.","Regression-test chunking for large states.","Upgrade core/provider versions to pick up chunking fixes."],"tags":["grpc","state-store","streaming","validation","protocol"],"analyzedSha":"c9def3e214014c1188faabfc4a5bde5095139765","analyzedAt":"2026-08-07T15:39:49.278Z","schemaVersion":2},"datasetVersion":"2026-08-07T21:17:07.882Z"}