influxdata/influxdb · error · ExecutePluginError

Failed to import plugin module '{}': {} Hint: Check for synt

Error message

Failed to import plugin module '{}': {}
Hint: Check for syntax errors or missing dependencies in Python files.

What it means

For multi-file plugins, load_function_from_module temporarily inserts the plugin directory into sys.path (under a lock) and imports the module. Any import failure — syntax error, missing dependency, bad package layout — is wrapped as ExecutePluginError::PluginError with the module name and the original Python exception text, plus the hint about syntax errors and missing dependencies. The original traceback text in '{}' is the real cause and must be read first.

Source

Thrown at influxdb3_py_api/src/system_py.rs:373

    // A plugin dir added after FileFinder cached the parent is invisible until
    // import caches are invalidated; retry once.
    let import_result = match py.import(module_name) {
        Err(e) if is_module_not_found(py, &e, module_name) => {
            let _ = py
                .import("importlib")
                .and_then(|m| m.call_method0("invalidate_caches"));
            py.import(module_name)
        }
        result => result,
    };

    // Always cleanup sys.path, even if import failed. The getattr lookup below
    // operates on the imported module object and no longer needs sys.path.
    let _ = sys_path.call_method1("pop", (0,));

    // Any import failure is the real load error and must not be masked.
    let module = import_result.map_err(|e| {
        ExecutePluginError::PluginError(anyhow!(
            "Failed to import plugin module '{}': {}\n\
             Hint: Check for syntax errors or missing dependencies in Python files.",
            module_name,
            e
        ))
    })?;

    module.getattr(function_name).map_err(|e| {
        // Only a missing attribute on the imported module means the entry-point
        // function is absent; surface anything else as the real cause.
        if e.is_instance_of::<PyAttributeError>(py) {
            missing_fn_error
        } else {
            ExecutePluginError::PluginError(anyhow!(
                "Failed to load function '{}' from plugin module '{}': {}",
                function_name,
                module_name,
                e

View on GitHub (pinned to d28e26e048)

Solutions

  1. Read the exception text after the module name — it names the missing module or the exact syntax error
  2. Byte-compile all plugin files before deploying: python -m py_compile plugin/__init__.py plugin/*.py
  3. Install missing dependencies into the server's plugin Python environment, or vendor them as files inside the plugin directory
  4. Confirm the plugin directory layout: __init__.py present, entry-point function defined, and syntax compatible with the server's Python version

Example fix

# before: __init__.py imports a package the server env lacks
import requests  # ModuleNotFoundError -> Failed to import plugin module

# after: vendor the dependency beside the plugin or use the stdlib
from plugin.vendor.requests import Session  # vendored copy shipped in the plugin dir
Defensive patterns

Strategy: try-catch

Validate before calling

# deploy-time check: byte-compile every plugin file before upload
python -m py_compile plugin/__init__.py plugin/*.py \
  || { echo "plugin has syntax errors — fix before deploy" >&2; exit 1; }

Try / catch

match execute_plugin(/* ... */).await {
    Err(ExecutePluginError::PluginError(e))
        if e.to_string().contains("Failed to import plugin module") =>
    {
        // surface the embedded Python error + hint to the plugin author verbatim
        Err(PluginLoadRejected(e))
    }
    other => other,
}

Prevention

When it happens

Trigger: A plugin whose __init__.py or sibling module has a syntax error; imports a third-party package absent from the server's Python environment; has no/corrupt __init__.py layout; or uses Python syntax newer than the interpreter embedded in the server.

Common situations: Plugin developed in a personal venv then deployed to the server runtime that lacks those packages; partial uploads (a module referenced but not shipped); Python version mismatch (e.g. match statements on an older interpreter); circular imports between plugin modules.

Related errors


AI-assisted analysis of influxdata/influxdb@d28e26e048 (2026-08-16). Data as JSON: /api/errors/387b65a31a1972e4. Report an issue: GitHub.