apache/beam · error

malformed components;

Error message

malformed components; %v lacks a conforming pipeline component

What it means

ExpandedComponents type-asserts an ExpandedTransform's Components field to *pipepb.Components. This error is returned when the stored value is nil or of a different type, meaning the expansion result does not carry a valid pipeline components proto.

Solutions

  1. Ensure the expansion path sets Components to a *pipepb.Components before use.
  2. Fix test fakes/custom code to store the correct proto type in ExpandedTransform.Components.
  3. Re-run the expansion with TryCrossLanguage rather than hand-populating ExpandedTransform.

Example fix

// before
exp := &graph.ExpandedTransform{Transform: &pipepb.PTransform{}}
// after
exp := &graph.ExpandedTransform{Transform: &pipepb.PTransform{}, Components: &pipepb.Components{}}
Defensive patterns

Strategy: type-guard

Type guard

func hasValidComponents(exp *graph.ExpandedTransform) bool {
    _, ok := exp.Components.(*pipepb.Components)
    return ok
}

Try / catch

if c, err := graphx.ExpandedComponents(exp); err != nil {
    return fmt.Errorf("expansion lacks components: %w", err)
}

Prevention

When it happens

Trigger: Calling ExpandedComponents (directly or via mergeExpandedWithPipeline, ResolveOutputIsBounded, ResolveArtifactsWithConfig, UpdateArtifactTypeFromFileToURL) on a graph.ExpandedTransform whose Components was never set to *pipepb.Components.

Common situations: Constructing graph.ExpandedTransform manually without a components proto; test fakes populating Components with the wrong type; corrupted expansion results stored under a different concrete type.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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

Appendix: source

Thrown at sdks/go/pkg/beam/core/runtime/graphx/xlang.go:241

		id := fmt.Sprintf("%s_%s", "impulse", tag)
		impulseIDs = append(impulseIDs, id)
	}

	for _, id := range impulseIDs {
		t := transforms[id]
		if t.GetSpec().GetUrn() == URNImpulse {
			delete(transforms, id)
		}
	}
}

// ExpandedComponents type asserts the Components field with any type
// and returns its pipeline component proto representation
func ExpandedComponents(exp *graph.ExpandedTransform) (*pipepb.Components, error) {
	if c, ok := exp.Components.(*pipepb.Components); ok {
		return c, nil
	}
	return nil, errors.Errorf("malformed components; %v lacks a conforming pipeline component", exp)
}

// ExpandedTransform type asserts the Transform field with any type
// and returns its pipeline ptransform proto representation
func ExpandedTransform(exp *graph.ExpandedTransform) (*pipepb.PTransform, error) {
	if t, ok := exp.Transform.(*pipepb.PTransform); ok {
		return t, nil
	}
	return nil, errors.Errorf("malformed transform; %v lacks a conforming pipeline ptransform", exp)
}

// ExternalInputs returns the map (tag -> graph node representing the
// pcollection) of input nodes with respect to the map (tag -> index of Inbound
// in MultiEdge.Input) of named inputs
func ExternalInputs(e *graph.MultiEdge) map[string]*graph.Node {
	return InboundTagToNode(e.External.InputsMap, e.Input)
}

View on GitHub (pinned to 12126d8942)