opentofu/opentofu · error
wrong number of operands (%d) for opManagedAlreadyDeposed
Error message
wrong number of operands (%d) for opManagedAlreadyDeposed
What it means
UnmarshalGraph rejects an opManagedAlreadyDeposed element whose operand list does not contain exactly 2 entries (instAddr, deposedKey). The operand count is fixed by the operation's contract with the Builder.ManagedAlreadyDeposed call, so any other count means the serialized payload does not follow the format this OpenTofu build expects.
Source
Thrown at internal/engine/internal/execgraph/graph_unmarshal.go:288
}
instAddr, err := unmarshalGetPrevResultOf[addrs.AbsResourceInstance](prevResults, rawOperands[0])
if err != nil {
return nil, fmt.Errorf("invalid unmarshalOpManagedDeposedMeta instAddr: %w", err)
}
deposedKey, err := unmarshalGetPrevResultOf[states.DeposedKey](prevResults, rawOperands[1])
if err != nil {
return nil, fmt.Errorf("invalid unmarshalOpManagedDeposedMeta deposedKey: %w", err)
}
prior, err := unmarshalGetPrevResultOf[*exec.ResourceInstanceObject](prevResults, rawOperands[2])
if err != nil {
return nil, fmt.Errorf("invalid unmarshalOpManagedDeposedMeta prior: %w", err)
}
return builder.ManagedDeposedMeta(instAddr, deposedKey, prior), nil
}
func unmarshalOpManagedAlreadyDeposed(rawOperands []uint64, prevResults []AnyResultRef, builder *Builder) (AnyResultRef, error) {
if len(rawOperands) != 2 {
return nil, fmt.Errorf("wrong number of operands (%d) for opManagedAlreadyDeposed", len(rawOperands))
}
instAddr, err := unmarshalGetPrevResultOf[addrs.AbsResourceInstance](prevResults, rawOperands[0])
if err != nil {
return nil, fmt.Errorf("invalid opManagedAlreadyDeposed instAddr: %w", err)
}
deposedKey, err := unmarshalGetPrevResultOf[states.DeposedKey](prevResults, rawOperands[1])
if err != nil {
return nil, fmt.Errorf("invalid opManagedAlreadyDeposed deposedKey: %w", err)
}
return builder.ManagedAlreadyDeposed(instAddr, deposedKey), nil
}
func unmarshalOpManagedChangeAddr(rawOperands []uint64, prevResults []AnyResultRef, builder *Builder) (AnyResultRef, error) {
if len(rawOperands) != 2 {
return nil, fmt.Errorf("wrong number of operands (%d) for opManagedChangeAddr", len(rawOperands))
}
currentObj, err := unmarshalGetPrevResultOf[*exec.ResourceInstanceObject](prevResults, rawOperands[0])
if err != nil {View on GitHub (pinned to 3561785c48)
Solutions
- Regenerate the graph artifact with the same OpenTofu version that reads it
- Check the artifact's integrity (hash) and replace it if corrupted
- Confirm producer and consumer versions match before exchanging serialized graphs
- If produced by Graph.Marshal unmodified, report the Marshal/Unmarshal mismatch as an OpenTofu bug
Example fix
// before: custom marshaler emits 3 operands for ManagedAlreadyDeposed
op := &execgraphproto.Operation{Operands: []uint64{instAddrIdx, deposedKeyIdx, extraIdx}}
// after: emit exactly the two operands the operation requires
op := &execgraphproto.Operation{Operands: []uint64{instAddrIdx, deposedKeyIdx}} Defensive patterns
Strategy: validation
Validate before calling
// Producers: assert operand counts before serializing each operation.
if len(operands) != 2 {
return fmt.Errorf("opManagedAlreadyDeposed needs 2 operands, got %d", len(operands))
} Try / catch
if err != nil {
// operand-count errors mean the artifact is unusable: regenerate, don't retry
return fmt.Errorf("rejecting execution graph artifact: %w", err)
} Prevention
- Pin graph producers and consumers to the same OpenTofu build
- Add round-trip tests (Marshal then Unmarshal) for every operation type you emit
- Reject artifacts whose protobuf schema version differs from the reader's
When it happens
Trigger: UnmarshalGraph reads an element whose WhichRequest() is Operation with the ManagedAlreadyDeposed opcode and len(rawOperands) != 2 — e.g. 0, 1, or 3+ operands in the protobuf operation record.
Common situations: Serialized graph written by an incompatible OpenTofu version that changed the operation signature; corrupted or hand-crafted protobuf operation records; partial writes leaving malformed fields.
Related errors
- invalid unmarshalOpManagedDeposedMeta prior: %w
- invalid opManagedAlreadyDeposed instAddr: %w
- invalid opManagedAlreadyDeposed deposedKey: %w
- wrong number of operands (%d) for opManagedChangeAddr
- invalid opManagedChangeAddr currentObj: %w
AI-assisted analysis of opentofu/opentofu@3561785c48 (2026-08-15).
Data as JSON: /api/errors/e5ad5dd864a82100.
Report an issue: GitHub.