{"record":{"id":"1c123e72327db91d","repo":"opentofu/opentofu","slug":"invalid-wire-format-w","errorCode":null,"errorMessage":"invalid wire format: %w","messagePattern":"invalid wire format: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/engine/internal/execgraph/graph_unmarshal.go","lineNumber":36,"sourceCode":"\t\"github.com/opentofu/opentofu/internal/engine/internal/execgraph/execgraphproto\"\n\t\"github.com/opentofu/opentofu/internal/lang/eval\"\n\t\"github.com/opentofu/opentofu/internal/states\"\n)\n\n// UnmarshalGraph takes some bytes previously returned by [Graph.Marshal] and\n// returns a graph that is functionally-equivalent to (but not necessarily\n// identical to) the original graph.\n//\n// Because this is working with data loaded from outside OpenTofu it returns\n// errors when encountering problems, but if it fails when unmarshaling an\n// unmodified result from [Graph.Marshal] then that represents a bug in either\n// this or that function: they should always be updated together so they are\n// implementing the same file format.\nfunc UnmarshalGraph(src []byte) (*Graph, error) {\n\tvar root execgraphproto.ExecutionGraph\n\terr := proto.Unmarshal(src, &root)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"invalid wire format: %w\", err)\n\t}\n\n\telems := root.GetElements()\n\t// During decoding we'll track the typed result ref corresponding to\n\t// each element from the serialized graph, which then allows us to\n\t// make sure that operands are actually of the types they ought to be\n\t// during our validation work.\n\tresults := make([]AnyResultRef, len(elems))\n\tbuilder := NewBuilder()\n\n\tfor idx, elem := range elems {\n\t\tif !elem.HasRequest() {\n\t\t\t// As a special case, a totally-unpopulated result is allowed to\n\t\t\t// coerce to any type when we're decoding operation arguments,\n\t\t\t// becoming the zero value of the target type.\n\t\t\tresults[idx] = nil\n\t\t\tcontinue\n\t\t}","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/opentofu/opentofu/blob/3561785c48c1ce615e7c50261bd351f26053efa2/internal/engine/internal/execgraph/graph_unmarshal.go#L18-L54","documentation":"UnmarshalGraph failed at the very first step: the input bytes could not be parsed as the protobuf wire format of execgraphproto.ExecutionGraph. The bytes are not a valid protobuf message of the expected schema, so no graph elements are even attempted.","triggerScenarios":"Passing truncated, corrupted, or non-graph bytes to UnmarshalGraph; feeding a file that is not a serialized execution graph at all; a payload produced by a proto schema incompatible at the wire level.","commonSituations":"Reading a truncated or partially-written graph artifact, passing a JSON/text file where binary proto was expected, or transmission corruption between producer and consumer.","solutions":["Regenerate the serialized execution graph with a working OpenTofu run instead of repairing the bytes","Verify the byte slice was produced by Graph.Marshal / the same OpenTofu engine version that is consuming it","Check for truncation: compare payload length/checksum against what the producer recorded"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Fail fast on obviously wrong payloads before graph decoding:\n// reject empty/truncated buffers and non-proto artifacts.\nfunc plausibleGraphPayload(src []byte) error {\n\tif len(src) == 0 {\n\t\treturn fmt.Errorf(\"empty serialized graph payload\")\n\t}\n\tvar probe execgraphproto.ExecutionGraph\n\tif err := proto.Unmarshal(src, &probe); err != nil {\n\t\treturn fmt.Errorf(\"not a serialized execution graph: %w\", err)\n\t}\n\treturn nil\n}","typeGuard":null,"tryCatchPattern":"g, err := execgraph.UnmarshalGraph(src)\nif err != nil {\n\tif strings.HasPrefix(err.Error(), \"invalid wire format\") {\n\t\treturn fmt.Errorf(\"corrupt or foreign payload, regenerate the graph: %w\", err)\n\t}\n\treturn err\n}","preventionTips":["Transport serialized graphs with checksums (sha256) and verify before unmarshaling","Write graph artifacts atomically (temp file + rename) to avoid truncation","Ensure producer and consumer use the same OpenTofu engine build"],"tags":["protobuf","serialization","graph","engine","corruption"],"backgroundTag":null,"analyzedSha":"3561785c48c1ce615e7c50261bd351f26053efa2","analyzedAt":"2026-08-15T23:27:16.226Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}