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

  1. Regenerate the graph artifact with the same OpenTofu version that reads it
  2. Check the artifact's integrity (hash) and replace it if corrupted
  3. Confirm producer and consumer versions match before exchanging serialized graphs
  4. 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

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


AI-assisted analysis of opentofu/opentofu@3561785c48 (2026-08-15). Data as JSON: /api/errors/e5ad5dd864a82100. Report an issue: GitHub.