apache/beam · error

external transforms like %v are not supported in the Go dire

Error message

external transforms like %v are not supported in the Go direct runner, please execute your pipeline on a different runner

What it means

makeLink translates each graph edge into an executable unit. When it encounters a graph.External edge (a cross-language transform), the Go direct runner cannot execute it and returns this hard error directing the developer to another runner. It is a deliberate capability limitation, not a data-dependent failure.

Source

Thrown at sdks/go/pkg/beam/runners/direct/direct.go:340

	case graph.Reshuffle:
		// Reshuffle is a no-op in the direct runner, as there's only a single bundle
		// on a single worker. Hoist the next node up in the cache.
		b.links[id] = out[0]
		return b.links[id], nil

	case graph.Flatten:
		u = &exec.Flatten{UID: b.idgen.New(), N: len(edge.Input), Out: out[0]}

		for i := 0; i < len(edge.Input); i++ {
			b.links[linkID{edge.ID(), i}] = u
		}

	case graph.WindowInto:
		u = &exec.WindowInto{UID: b.idgen.New(), Fn: edge.WindowFn, Out: out[0]}

	case graph.External:
		return nil, errors.Errorf("external transforms like %v are not supported in the Go direct runner, please execute your pipeline on a different runner", edge)

	default:
		return nil, errors.Errorf("unexpected edge: %v", edge)
	}

	b.links[id] = u
	b.units = append(b.units, u)
	return u, nil
}

View on GitHub (pinned to 12126d8942)

Solutions

  1. Run the pipeline on a runner that supports external transforms (Dataflow, Flink, Spark) instead of 'direct'.
  2. Replace the external transform with a pure-Go equivalent transform if one exists.
  3. Use the expansion service only with a compatible runner; check docs for Go-native alternatives of the needed IO.
  4. Isolate xlang usage in a separate pipeline stage executed on a supported runner.

Example fix

// before
beam.Run(ctx, "direct", p) // pipeline contains Java Kafka IO external transform
// after
beam.Run(ctx, runner, p) // runner from --runner=flink / dataflow, which supports external transforms
Defensive patterns

Strategy: validation

Validate before calling

// fail fast if the pipeline contains cross-language transforms
for _, t := range pipelineTransforms(p) {
    if isExternal(t) {
        return fmt.Errorf("transform %v is external; use flink/dataflow runner", t)
    }
}

Try / catch

if _, err := beam.Run(ctx, runner, p); err != nil && strings.Contains(err.Error(), "not supported in the Go direct runner") {
    log.Printf("re-run with a distributed runner: %v", err)
}

Prevention

When it happens

Trigger: Running a pipeline containing cross-language transforms (e.g. Java/Python external transforms added via beam.CrossLanguageTransform / xlang expansion) on the Go direct runner.

Common situations: Go pipelines incorporating transforms from the Java or Python SDK (Kafka IO, SQL, TFX); examples copied from docs that rely on xlang; teams testing locally with 'direct' before submitting to Flink/Spark/Dataflow.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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