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
- Run the pipeline on a runner that supports external transforms (Dataflow, Flink, Spark) instead of 'direct'.
- Replace the external transform with a pure-Go equivalent transform if one exists.
- Use the expansion service only with a compatible runner; check docs for Go-native alternatives of the needed IO.
- 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
- Check the transform list for xlang/external transforms before choosing the direct runner.
- Maintain pure-Go alternatives for IOs you need locally.
- Document which runners your pipeline supports.
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
- error in startAutomatedJavaExpansionService(%s,%s): %w
- error in starting expansion service, StartService(): %w
- inputs already set as: %v
- outputTypes already set as: %v
- strictness check failed
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/63f0384796f01b93.
Report an issue: GitHub.