{"record":{"id":"3b923b385d52333d","repo":"apache/beam","slug":"method-expand-has-not-been-implemented","errorCode":null,"errorMessage":"Method expand has not been implemented.","messagePattern":"Method expand has not been implemented\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"sdks/typescript/src/apache_beam/transforms/transform.ts","lineNumber":96,"sourceCode":"// Note also that the requirement for both a synchronous and asynchronous\n// variant is imposed by javascript, and is not necessarily relevant in other\n// languages (especially if an asynchronous call can be turned into a blocking\n// call rather than forcing the asynchronous nature all the way up the call\n// hierarchy).\n\n/** @internal */\nexport class AsyncPTransformClass<\n  InputT extends PValue<any>,\n  OutputT extends PValue<any>,\n> {\n  beamName: string | (() => string);\n\n  constructor(name: string | (() => string) | null = null) {\n    this.beamName = name || this.constructor.name;\n  }\n\n  async expandAsync(input: InputT): Promise<OutputT> {\n    throw new Error(\"Method expand has not been implemented.\");\n  }\n\n  async expandInternalAsync(\n    input: InputT,\n    pipeline: Pipeline,\n    transformProto: runnerApi.PTransform,\n  ): Promise<OutputT> {\n    return this.expandAsync(input);\n  }\n}\n\n/** @internal */\nexport class PTransformClass<\n  InputT extends PValue<any>,\n  OutputT extends PValue<any>,\n> extends AsyncPTransformClass<InputT, OutputT> {\n  expand(input: InputT): OutputT {\n    throw new Error(\"Method expand has not been implemented.\");","sourceCodeStart":78,"sourceCodeEnd":114,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/typescript/src/apache_beam/transforms/transform.ts#L78-L114","documentation":"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.","triggerScenarios":"Extending AsyncPTransformClass and calling expandAsync (directly or via expandInternalAsync) without overriding expandAsync; instantiating the base class directly.","commonSituations":"Writing a custom composite transform and forgetting to implement the expansion method; renaming/refactoring that removed the override.","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."],"exampleFix":"// before\nclass MyTransform extends AsyncPTransformClass<PCollection<string>, PCollection<number>> {}\n\n// after\nclass MyTransform extends AsyncPTransformClass<PCollection<string>, PCollection<number>> {\n  async expandAsync(input: PCollection<string>): Promise<PCollection<number>> {\n    return input.map(s => s.length).withName(\"lengths\");\n  }\n}","handlingStrategy":"type-guard","validationCode":"function overridesExpandAsync(t: object): boolean {\n  return t.constructor !== AsyncPTransformClass &&\n    t['expandAsync'] !== AsyncPTransformClass.prototype.expandAsync;\n}","typeGuard":"const implementsExpandAsync = (t: unknown): t is { expandAsync(i: never): Promise<unknown> } =>\n  typeof (t as any)?.expandAsync === 'function' &&\n  (t as any).expandAsync !== AsyncPTransformClass.prototype.expandAsync;","tryCatchPattern":"try {\n  await pipeline.runInternal();\n} catch (e) {\n  if (/Method expand has not been implemented/.test(String(e)))\n    throw new Error('Your custom PTransform must override expandAsync');\n  throw e;\n}","preventionTips":["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."],"tags":["abstract-method","transform","pipeline-build"],"backgroundTag":"method-not-implemented","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}