apache/beam · critical · Error
Method expand has not been implemented.
Error message
Method expand has not been implemented.
What it means
AsyncPTransformClass.expandAsync is the abstract expansion method; the base class throws this error if it is invoked without being overridden. It means a custom PTransform subclass (or one reaching this base implementation) never implemented expandAsync, so the pipeline cannot expand the transform into primitive operations.
Solutions
- Override expandAsync(input) in your subclass and return the expanded PValue.
- If your transform is synchronous, extend PTransformClass and implement expand() instead.
- Do not instantiate AsyncPTransformClass directly — it is an abstract base.
Example fix
// before
class MyTransform extends AsyncPTransformClass<PCollection<string>, PCollection<number>> {}
// after
class MyTransform extends AsyncPTransformClass<PCollection<string>, PCollection<number>> {
async expandAsync(input: PCollection<string>): Promise<PCollection<number>> {
return input.map(s => s.length).withName("lengths");
}
} Defensive patterns
Strategy: type-guard
Validate before calling
function overridesExpandAsync(t: object): boolean {
return t.constructor !== AsyncPTransformClass &&
t['expandAsync'] !== AsyncPTransformClass.prototype.expandAsync;
} Type guard
const implementsExpandAsync = (t: unknown): t is { expandAsync(i: never): Promise<unknown> } =>
typeof (t as any)?.expandAsync === 'function' &&
(t as any).expandAsync !== AsyncPTransformClass.prototype.expandAsync; Try / catch
try {
await pipeline.runInternal();
} catch (e) {
if (/Method expand has not been implemented/.test(String(e)))
throw new Error('Your custom PTransform must override expandAsync');
throw e;
} Prevention
- Subclass the abstract transform classes, never instantiate them.
- Implement expandAsync (or expand for PTransformClass) in every subclass.
- Add a unit test that expands every custom transform before running the pipeline.
When it happens
Trigger: Extending AsyncPTransformClass and calling expandAsync (directly or via expandInternalAsync) without overriding expandAsync; instantiating the base class directly.
Common situations: Writing a custom composite transform and forgetting to implement the expansion method; renaming/refactoring that removed the override.
Related errors
- A transform cannot be initiated using the provided config…
- Could not find a transform with the ID
- Decode not implemented
- Encode not implemented
- Error applying transform
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/3b923b385d52333d.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/typescript/src/apache_beam/transforms/transform.ts:96
// Note also that the requirement for both a synchronous and asynchronous
// variant is imposed by javascript, and is not necessarily relevant in other
// languages (especially if an asynchronous call can be turned into a blocking
// call rather than forcing the asynchronous nature all the way up the call
// hierarchy).
/** @internal */
export class AsyncPTransformClass<
InputT extends PValue<any>,
OutputT extends PValue<any>,
> {
beamName: string | (() => string);
constructor(name: string | (() => string) | null = null) {
this.beamName = name || this.constructor.name;
}
async expandAsync(input: InputT): Promise<OutputT> {
throw new Error("Method expand has not been implemented.");
}
async expandInternalAsync(
input: InputT,
pipeline: Pipeline,
transformProto: runnerApi.PTransform,
): Promise<OutputT> {
return this.expandAsync(input);
}
}
/** @internal */
export class PTransformClass<
InputT extends PValue<any>,
OutputT extends PValue<any>,
> extends AsyncPTransformClass<InputT, OutputT> {
expand(input: InputT): OutputT {
throw new Error("Method expand has not been implemented.");View on GitHub (pinned to 12126d8942)