apache/pulsar · critical · NameError

Could not import User Function Module %s

Error message

Could not import User Function Module %s

What it means

python_instance.run imports the user's function class via util.import_class using the configured className. If the import returns None (module or class not found), Pulsar logs it as critical and raises NameError('Could not import User Function Module %s'), meaning the Python class specified in functionDetails.className could not be loaded from the user code directory.

Source

Thrown at pulsar-functions/instance/src/main/python/python_instance.py:231

      consumer_args.update(nack_args)
      if consumer_conf.HasField("receiverQueueSize"):
        consumer_args["receiver_queue_size"] = consumer_conf.receiverQueueSize.value

      if consumer_conf.isRegexPattern:
        self.consumers[topic] = self.pulsar_client.subscribe(
          re.compile(str(topic)), subscription_name,
          **consumer_args
        )
      else:
        self.consumers[topic] = self.pulsar_client.subscribe(
          str(topic), subscription_name,
          **consumer_args
        )

    function_kclass = util.import_class(os.path.dirname(self.user_code), self.instance_config.function_details.className)
    if function_kclass is None:
      Log.critical("Could not import User Function Module %s" % self.instance_config.function_details.className)
      raise NameError("Could not import User Function Module %s" % self.instance_config.function_details.className)
    try:
      self.function_class = function_kclass()
    except:
      self.function_purefunction = function_kclass

    self.contextimpl = contextimpl.ContextImpl(self.instance_config, Log, self.pulsar_client,
                                               self.user_code, self.consumers,
                                               self.secrets_provider, self.metrics_labels,
                                               self.state_context, self.stats)
    # Now launch a thread that does execution
    self.execution_thread = threading.Thread(target=self.actual_execution)
    self.execution_thread.start()

    # start proccess spawner health check timer
    self.last_health_check_ts = time.time()
    if self.expected_healthcheck_interval > 0:
      timer = util.FixedTimer(self.expected_healthcheck_interval, self.process_spawner_health_check_timer, name="health-check-timer")
      timer.start()

View on GitHub (pinned to 820761864e)

Solutions

  1. Set functionDetails.className to 'module_name.ClassName' exactly matching the file/class in the user code archive.
  2. Verify the user code zip/dir contains the module at its root or correct package path and includes __init__.py files.
  3. Test importing the class locally with the same Python runtime before deploying.
  4. Fix any module-level import errors (missing pip dependencies bundled with the function).

Example fix

# before (config)
className: myfunc.myfunction  # wrong path, module named my_function
# after
className: my_function.MyFunction
Defensive patterns

Strategy: validation

Validate before calling

import importlib, sys
mod, cls = 'my_function', 'MyFunction'
assert mod in sys.modules or importlib.util.find_spec(mod), f"module {mod} missing"
assert callable(getattr(importlib.import_module(mod), cls)), f"class {cls} missing"

Try / catch

try:
    # instance startup handled by framework
    run_instance()
except NameError as e:
    logging.critical('user function class not importable: %s', e)
    sys.exit(3)

Prevention

When it happens

Trigger: className in the function config doesn't match module.ClassName available under the user code path; the user code directory (self.user_code) is wrong or the file isn't distributed; a missing __init__.py or import error inside the module causing the import to fail and return None.

Common situations: Typos in the fully qualified class name (e.g. myfunc.MyFunction vs functions/my_function.py); uploading a zip without the expected package structure; module-level import failure due to a missing third-party dependency.

Related errors


AI-assisted analysis of apache/pulsar@820761864e (2026-09-06). Data as JSON: /api/errors/34f51fcbcf453c11. Report an issue: GitHub.