{"record":{"id":"478a094a6cddea80","repo":"influxdata/influxdb","slug":"failed-to-load-function-function-name-from-plugin-module","errorCode":null,"errorMessage":"Failed to load function '{function_name}' from plugin module '{module_name}': {e}","messagePattern":"Failed to load function '(.+?)' from plugin module '(.+?)': (.+?)","errorType":"error_code","errorClass":"ExecutePluginError::PluginError","httpStatus":null,"severity":"error","filePath":"influxdb3_py_api/src/system_py.rs","lineNumber":383,"sourceCode":"    let _ = sys_path.call_method1(\"pop\", (0,));\n\n    // Any import failure is the real load error and must not be masked.\n    let module = import_result.map_err(|e| {\n        ExecutePluginError::PluginError(anyhow!(\n            \"Failed to import plugin module '{}': {}\\n\\\n             Hint: Check for syntax errors or missing dependencies in Python files.\",\n            module_name,\n            e\n        ))\n    })?;\n\n    module.getattr(function_name).map_err(|e| {\n        // Only a missing attribute on the imported module means the entry-point\n        // function is absent; surface anything else as the real cause.\n        if e.is_instance_of::<PyAttributeError>(py) {\n            missing_fn_error\n        } else {\n            ExecutePluginError::PluginError(anyhow!(\n                \"Failed to load function '{}' from plugin module '{}': {}\",\n                function_name,\n                module_name,\n                e\n            ))\n        }\n    })\n}\n\n/// Execute a WAL flush trigger plugin.\npub fn execute_wal_flush_trigger(\n    code: &str,\n    wal_data: &[WalFlushElement],\n    schema: Arc<DatabaseSchema>,\n    query_endpoint: Arc<dyn QueryEndpoint>,\n    write_endpoint: Arc<dyn WriteEndpoint>,\n    logger: PluginLogger,\n    table_filter: Option<TableId>,","sourceCodeStart":365,"sourceCodeEnd":401,"githubUrl":"https://github.com/influxdata/influxdb/blob/06200ef96ba82c5f6727e5038a83af8e722c6875/influxdb3_py_api/src/system_py.rs#L365-L401","documentation":"Thrown when the plugin module imported successfully but `module.getattr(function_name)` fails with something other than a plain missing attribute (e.g. AttributeError whose getter raised, TypeError, or another Python exception during attribute access). A plain missing function yields a distinct 'missing function' error; this error surfaces all other getattr failures with their original cause.","triggerScenarios":"load_plugin_function asks for a trigger function name that exists as an attribute whose access raises — e.g. the module defines `function_name` as a property/descriptor that raises, name is shadowed by an object whose __getattr__ throws, or a module-level __getattr__ hook raises instead of raising AttributeError cleanly.","commonSituations":"Plugin defines the trigger name but assignment itself failed silently earlier; module uses `__getattr__` lazy loading that throws; a typo'd decorator wraps the function in an object that errors on access; Python module partially executed after a caught exception left names unbound.","solutions":["Inspect the wrapped Python exception text — it shows why attribute access failed; fix that in the plugin file.","Confirm the entry-point function is defined at module top level with the exact name passed to load_plugin_function: `def _trigger(...)` matching the configured name.","Remove any custom __getattr__/module-level magic in the plugin; define the function directly.","Simplify the plugin to a minimal `def trigger(...): pass` and reload to isolate whether the failure is in the function definition chain."],"exampleFix":"// before (plugin my_plugin.py)\nclass Wrapper:\n    def __getattr__(self, name):\n        raise RuntimeError(\"boom\")\ntrigger = Wrapper()\n// after\ndef trigger(args):\n    ...","handlingStrategy":"try-catch","validationCode":"// verify the entry point exists before triggering a load\nimport subprocess, sys, json\nr = subprocess.run([sys.executable, \"-c\",\n  f\"import {module_name}; print(hasattr({module_name}, '{fn_name}'))\"],\n  capture_output=True, text=True, cwd=plugin_parent_dir)\nif r.stdout.strip() != \"True\":\n    raise SystemExit(f\"Function '{fn_name}' not found in plugin '{module_name}'\")","typeGuard":null,"tryCatchPattern":"try {\n  loadPluginFunction(dir, module, fn);\n} catch (e) {\n  if (String(e.message).includes(\"Failed to load function\")) {\n    console.error(`Entry point '${fn}' inaccessible in '${module}': ${e.message}`);\n  } else throw e;\n}","preventionTips":["Define the trigger function at module top level with the exact configured name.","Avoid custom __getattr__ or descriptor magic in plugin modules.","After edits, reload/restart so a partially executed module can't leave names unbound.","Keep a smoke test that imports each plugin and asserts the trigger attribute exists."],"tags":["python-plugins","attribute-error","function-lookup"],"backgroundTag":"class-not-found","analyzedSha":"06200ef96ba82c5f6727e5038a83af8e722c6875","analyzedAt":"2026-09-19T12:55:30.003Z","contentChangedAt":"2026-09-19T12:55:30.003Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}