apache/beam · error

unexpected opcode

Error message

unexpected opcode: %v

What it means

During pipeline graph marshalling (graphx/translate.go), addMultiEdge converts each in-memory MultiEdge's Operation opcode into a Beam runner-API transform payload. The 'default' branch of the opcode switch is reached when the opcode is not one of the recognized ones (ParDo, GBK, CoGBK, Reshuffle, External, etc.), so the marshaller fails fast with 'unexpected opcode'. This indicates an operation kind the translator does not know how to serialize.

Solutions

  1. Update translate.go's opcode switch in addMultiEdge to handle the new graph.Op value and emit the appropriate pipepb transform payload
  2. Verify the pipeline is built with public beam APIs; manually constructed graphs may carry invalid opcodes
  3. Check Go SDK version: code written against a newer graph.Op enum running with an older translate.go needs upgrading
  4. File/report upstream to apache/beam if the op is a standard one that should be supported

Example fix

// before (translate.go addMultiEdge switch)
default:
    err := errors.Errorf("unexpected opcode: %v", edge.Edge.Op)
    return handleErr(err)
// after
case graph.MyNewOp:
    return m.expandMyNewOp(edge)
default:
    err := errors.Errorf("unexpected opcode: %v", edge.Edge.Op)
    return handleErr(err)
Defensive patterns

Strategy: validation

Validate before calling

// pre-flight: only known ops can be marshalled
known := map[graph.Op]bool{graph.ParDo: true, graph.CoGBK: true, graph.Reshuffle: true, graph.External: true}
if !known[edge.Edge.Op] {
    return fmt.Errorf("op %v not supported by graphx marshaller", edge.Edge.Op)
}

Type guard

func isKnownOp(op graph.Op) bool {
    switch op {
    case graph.ParDo, graph.CoGBK, graph.Reshuffle, graph.External:
        return true
    }
    return false
}

Prevention

When it happens

Trigger: A MultiEdge whose edge.Op is a new/unhandled graph.Op value reaches Marshal — e.g. a custom or newly added Operation type in the beam graph package that translate.go's switch has not been extended for, or a manually constructed graph passed to graphx.Marshal.

Common situations: Developers hacking on Beam internals adding a new operation kind without updating the marshaller; running a fork of the Go SDK where an op was introduced but translation support wasn't; building synthetic pipelines programmatically with an invalid op.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/55cb913241d09c44. Report an issue: GitHub.

Appendix: source

Thrown at sdks/go/pkg/beam/core/runtime/graphx/translate.go:715

				inputs[tag] = nodeID(in)
			}
		}

		if len(pyld.OutputsMap) != 0 {
			if got, want := len(pyld.OutputsMap), len(edge.Edge.Output); got != want {
				return handleErr(errors.Errorf("mismatch'd counts between External tags (%v) and outputs (%v)", got, want))
			}
			outputs = make(map[string]string)
			for tag, out := range OutboundTagToNode(pyld.OutputsMap, edge.Edge.Output) {
				if _, err := m.addNode(out); err != nil {
					return handleErr(err)
				}
				outputs[tag] = nodeID(out)
			}
		}

	default:
		err := errors.Errorf("unexpected opcode: %v", edge.Edge.Op)
		return handleErr(err)
	}

	var transformEnvID = ""
	if !(spec.Urn == URNGBK || spec.Urn == URNImpulse) {
		transformEnvID = m.addDefaultEnv()
	}

	transform := &pipepb.PTransform{
		UniqueName:    edge.Name,
		Spec:          spec,
		Inputs:        inputs,
		Outputs:       outputs,
		EnvironmentId: transformEnvID,
		Annotations:   annotations,
	}
	m.transforms[id] = transform
	allPIds = append(allPIds, id)

View on GitHub (pinned to 12126d8942)