{"record":{"id":"d4db585005df3820","repo":"apache/beam","slug":"cannot-be-called-outside-of-a-dofn-s-process-method","errorCode":null,"errorMessage":"Cannot be called outside of a DoFn's process method.","messagePattern":"Cannot be called outside of a DoFn's process method\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"sdks/typescript/src/apache_beam/transforms/pardo.ts","lineNumber":311,"sourceCode":" */\nexport class ParDoParam {\n  // Provided externally.\n  /** @internal */\n  protected provider: ParamProvider | undefined;\n\n  /** @internal */\n  constructor(readonly parDoParamName: string) {}\n}\n\n/**\n * At runtime, one can invoke the special `lookup` method to retrieve the\n * relevant value associated with the currently-being-processed element.\n */\nexport class ParDoLookupParam<T> extends ParDoParam {\n  // TODO: Nameing \"get\" seems to be special.\n  lookup(): T {\n    if (this.provider === undefined) {\n      throw new Error(\"Cannot be called outside of a DoFn's process method.\");\n    }\n\n    return this.provider.lookup(this);\n  }\n}\n\n/**\n * At runtime, one can invoke the special `update` method to update the\n * relevant value associated with the currently-being-processed element.\n */\nexport class ParDoUpdateParam<T> extends ParDoParam {\n  update(value: T): void {\n    if (this.provider === undefined) {\n      throw new Error(\"Cannot be called outside of a DoFn's process method.\");\n    }\n\n    this.provider.update(this, value);\n  }","sourceCodeStart":293,"sourceCodeEnd":329,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/typescript/src/apache_beam/transforms/pardo.ts#L293-L329","documentation":"ParDoLookupParam.lookup() requires a side-input provider that is only injected while a DoFn's process method runs. If provider is undefined — meaning lookup() was called outside element processing — it throws 'Cannot be called outside of a DoFn's process method.'","triggerScenarios":"Calling sideInput.lookup() (a ParDoLookupParam captured in the DoFn) from setup/teardown/startBundle/finishBundle, from the constructor, or from plain application code outside the pipeline.","commonSituations":"Developers caching the side-input object and calling lookup() at class level or in unit tests without executing through the DoFn process pipeline context.","solutions":["Move the lookup() call inside the DoFn's processElement/process method where the provider is bound.","For tests, construct a ParDoLookupParam with a mock provider set instead of relying on runtime injection.","Use startBundle/process-scoped state to store values you need outside process."],"exampleFix":"// before\nclass MyFn extends DoFn {\n  setup() { this.value = this.sideInput.lookup(); } // throws\n}\n// after\nclass MyFn extends DoFn {\n  processElement(e) { const v = this.sideInput.lookup(); ... }\n}","handlingStrategy":"validation","validationCode":"function canLookup(param: ParDoLookupParam<T>) { return param.provider !== undefined; }\nif (!canLookup(sideInput)) console.warn(\"lookup() only valid inside processElement\");","typeGuard":"function inProcessContext<T>(p: ParDoLookupParam<T>): p is ParDoLookupParam<T> & { provider: NonNullable<ParDoLookupParam<T>[\"provider\"]> } {\n  return p.provider !== undefined;\n}","tryCatchPattern":"try {\n  const v = this.sideInput.lookup();\n} catch (e) {\n  if (e.message.includes(\"outside of a DoFn's process method\")) {\n    throw new Error(\"Move side-input lookup into processElement\");\n  } else throw e;\n}","preventionTips":["Only call side-input lookup/update inside processElement","Never call side-input APIs from setup/teardown/startBundle/finishBundle","Inject mock providers in unit tests"],"tags":["side-input","dofn","lifecycle"],"backgroundTag":"invalid-state-transition","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-15T02:17:10.978Z"}