{"record":{"id":"d88de507bb7aad04","repo":"apache/beam","slug":"cannot-import-constructor-as-fully-qualified-name","errorCode":null,"errorMessage":"Cannot import {constructor} as {fully_qualified_name}.","messagePattern":"Cannot import (.+?) as (.+?)\\.","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"sdks/python/apache_beam/transforms/ptransform.py","lineNumber":1242,"sourceCode":"  \"\"\"Causes instances of this transform to be annotated with their yaml syntax.\n\n  Should only be used for transforms that are fully defined by their constructor\n  arguments.\n  \"\"\"\n  @wraps(constructor)\n  def wrapper(*args, **kwargs):\n    transform = constructor(*args, **kwargs)\n\n    fully_qualified_name = (\n        f'{constructor.__module__}.{constructor.__qualname__}')\n    try:\n      imported_constructor = (\n          python_callable.PythonCallableWithSource.\n          load_from_fully_qualified_name(fully_qualified_name))\n      if imported_constructor != wrapper:\n        raise ImportError('Different object.')\n    except ImportError:\n      warnings.warn(f'Cannot import {constructor} as {fully_qualified_name}.')\n      return transform\n\n    try:\n      config = json.dumps({\n          'constructor': fully_qualified_name,\n          'args': args,\n          'kwargs': kwargs,\n      })\n    except TypeError as exn:\n      warnings.warn(\n          f'Cannot serialize arguments for {constructor} as json: {exn}')\n      return transform\n\n    original_annotations = transform.annotations\n    transform.annotations = lambda: {\n        **original_annotations(),\n        # These override whatever may have been provided earlier.\n        # The outermost call is expected to be the most specific.","sourceCodeStart":1224,"sourceCodeEnd":1260,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/transforms/ptransform.py#L1224-L1260","documentation":"When capturing a transform's configuration, Beam attempts to round-trip the constructor by loading it from a fully qualified name (PythonCallableWithSource.load_from_fully_qualified_name) and comparing it to the original wrapper. If the import fails (or the loaded object differs), it warns 'Cannot import <constructor> as <fully_qualified_name>' and returns the transform unannotated, so cross-language/spec-based reconstruction of the transform won't be possible.","triggerScenarios":"Annotating a ptransform whose callable is defined in a __main__ script, a notebook, or a module not importable in the target environment (different sys.path, package not installed).","commonSituations":"Notebook/local pipeline definitions submitted to Dataflow or Flink; dynamically defined lambdas/functions; packaging mismatches between submit and worker environments.","solutions":["Move the constructor/callable into an installable module available on both the submitting and worker environments and reference it by its real module path.","Ensure the module's import path matches the fully qualified name (avoid __main__; run via python -m or restructure).","Pin the same package versions on submit and run environments so the loaded object equals the wrapper.","Ignore the warning if spec-based serialization of this transform is not needed."],"exampleFix":"# before (in script run directly)\ndef my_callable(): ...\n# after\n# my_pkg/transforms.py\ndef my_callable(): ...\n# then use my_pkg.transforms.my_callable and install my_pkg in workers","handlingStrategy":"validation","validationCode":"import importlib\nmodule, _, name = 'my_pkg.transforms'.rpartition('.')\nassert hasattr(importlib.import_module(module), name), 'constructor not importable from workers'","typeGuard":null,"tryCatchPattern":"import warnings\nwith warnings.catch_warnings(record=True) as w:\n    warnings.simplefilter('always')\n    # build pipeline\n    if any('Cannot import' in str(x.message) for x in w):\n        print('transform spec annotation skipped; ensure constructor is importable on workers')","preventionTips":["Define callables in installable modules, never in __main__ or notebooks","Ensure identical package versions on submit and worker environments","Test that every callable referenced by a pipeline can be imported in a clean container"],"tags":["serialization","import","portability","callable"],"backgroundTag":"module-init-failed","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}