You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The plugin loader (autobot_shared/plugin_sdk/loader.py:275) registers plugins via importlib.import_module(manifest.entry_point). Core plugins live under plugins/core-plugins/<name>/ (hyphenated dir) but declare entry_point: "plugins.core_plugins.<name>.main" (underscored module path). There is no path hook, namespace package, __init__.py, or dir alias that maps the hyphenated directory to the underscored importable module, so the import fails.
Evidence
python3 -c "import importlib; importlib.import_module('plugins.core_plugins.image_generation_plugin.main')"
# ModuleNotFoundError: No module named 'plugins.core_plugins'
Impact
The image-generation-plugin (GH#9015) and the new video-generation-plugin (GH#9016) both fail to load through the plugin loader, so their initialize() never registers generate_image / generate_video into the tool_sdk registry via the loader path.
The REST endpoints still work (they import the provider/tool logic directly via file path), but the intended LLC-agent tool_sdk registry registration relies on the loader.
Suggested fix (wire it in, don't delete)
Add a plugin-path resolver in PluginLoader._import_plugin_class that, when import_module fails, falls back to importlib.util.spec_from_file_location using the manifest's on-disk directory (mapping core_plugins <-> core-plugins and <name>_plugin <-> <name>-plugin), registering the module in sys.modules so dataclasses resolve. The video-generation API already does this for its providers (autobot-backend/api/_video_providers_loader.py) and can serve as the reference.
Deploy half fixed in #10447 (merged): backend role now syncs code_source/plugins/ → backend_code_dir/plugins/, so discover_plugins() finds the core plugins (the Plugin directory does not exist flood is gone — validated on the box). The import half (file-path fallback for hyphenated dirs) lands via #10442. This issue fully resolves once #10442 merges.
Merged to Dev_new_gui (4d5f464bd). Plugin-loader file-path fallback for core-plugins (hyphen-dir → underscore module) merged; loader now resolves image/video-generation plugins via spec_from_file_location with Plugin alias + BasePlugin fallback. Batch #10440.
Reopening — the file-path fallback added for this issue does not work. Two core plugins still fail to
import on every backend start, observed on 84b88baa1591 after a clean host boot.
Current failure
ERROR autobot_shared.plugin_sdk.loader: Failed to import plugin module:
plugins.core_plugins.image_generation_plugin.main
WARN File-path fallback failed for 'plugins.core_plugins.image_generation_plugin.main'
at plugins/core-plugins/image-generation-plugin/main.py: No module named 'plugins.core_plugins'
ERROR autobot_shared.plugin_sdk.loader: Failed to import plugin module:
plugins.core_plugins.video_generation_plugin.main
WARN File-path fallback failed for 'plugins.core_plugins.video_generation_plugin.main'
at plugins/core-plugins/video-generation-plugin/main.py: No module named 'plugins.core_plugins'
The fallback is present and attributed to this issue:
It locates the correct file — the warning names plugins/core-plugins/image-generation-plugin/main.py,
which exists — and then still raises No module named 'plugins.core_plugins'. So the fallback resolves the
path and then imports by dotted name anyway, which is the exact failure it was meant to bypass.
The underlying mismatch is unchanged
entry_point uses underscores; the directories use hyphens:
entry_point plugins.core_plugins.image_generation_plugin.main
on disk plugins/core-plugins/image-generation-plugin/
Image generation and video generation are both unavailable, and the failure is quiet — the backend starts active and healthy. The log also shows these two plugins reporting loaded with optional env vars unset: ['OPENAI_API_KEY', 'FLUX_API_KEY', 'STABILITY_API_KEY'] shortly before the import fails, so a reader
skimming the log sees "loaded" and an unrelated-looking import error separately.
Suggested fix
Have the fallback load from the located file — importlib.util.spec_from_file_location with a synthetic
module name — rather than re-attempting a dotted import. A test that loads every manifest under plugins/core-plugins/ would cover all seven and stop this reopening a third time.
Related: the same loader has two further defects filed separately (dependency check consulting the wrong
registry; discovery running twice).
This issue appears as a checklist item on #13852. Whoever moves it is responsible for the
umbrella staying accurate — the umbrella is the only place the ordering and the shared acceptance
criterion live, so a stale checklist there silently breaks the sequencing for everything else.
Eleven findings from one diagnostic session sharing a single property: the system was failing and
nothing said so — or something said the opposite. The umbrella's acceptance criterion is the part
no individual child owns:
A service that is running but not working must be distinguishable from one that is working, by
something a check can query — not by reading logs.
systemctl is-active returned active through four separate incidents in that session.
#12460/#13736 is linked on the umbrella as the worked example to copy — metric plus alert rule,
verified end-to-end against the worker's own log for the same synthesis.
Driving the real PluginLoader against the real plugins/ tree:
loaded=0 failed=7
So #13677's headline holds exactly. But it is three distinct causes, not one, and only two of them are
what the issues currently describe. The one that affects the most plugins is not mentioned anywhere.
ERROR: No plugin class found in module: plugins.core_plugins.hello_plugin.main
The module imports fine. The class is there. The loader simply cannot recognise it:
plugins/core-plugins/hello-plugin/main.py:15
from plugin_sdk.base import BasePlugin <- bare `plugin_sdk`
autobot_shared/plugin_sdk/loader.py
issubclass(attr, BasePlugin) <- autobot_shared.plugin_sdk.base.BasePlugin
Verified they are different class objects:
canonical: autobot_shared.plugin_sdk.base
alt : plugin_sdk.base
SAME CLASS OBJECT: False
issubclass is therefore False and the loader reports "No plugin class found" — an error message that sends
the reader looking for a missing class that is right there. This is the single largest route and it is
described in neither #10294 nor #13677.
Route 2 — the file-path fallback loads the file, then its own imports fail (2 of 7)
This is #10294's remaining bug, and the umbrella's phrasing is nearly right:
WARNING: File-path fallback failed for 'plugins.core_plugins.image_generation_plugin.main'
at plugins/core-plugins/image-generation-plugin/main.py: No module named 'plugins.core_plugins'
The fallback does locate the file and does use spec_from_file_location — that part of #10294 is
already implemented. What fails is exec_module: the plugin's own transitive imports reference plugins.core_plugins.*, and those parent packages exist nowhere in sys.modules. So the fix is not "load
from the located file" (already done) but "make the package path resolvable for the module's own imports" —
register synthetic namespace packages for plugins, plugins.core_plugins, and the plugin dir before exec_module.
Note the fallback also hardcodes main.py, while telemetry-prompt-middleware declares entry_point: ...telemetry_prompt_middleware.plugin and ships plugin.py. The last path segment should drive
the filename.
Relates to #13677's "dependency check resolves pip packages against the plugin registry".
Why this matches the umbrella
Every route fails silently at the fleet level: nothing emits loaded N of M, so 0-of-7 and
"no plugins installed" are the same observation. Route 1 is worse than silent — it emits a confident error
naming the wrong thing.
PR #13944 merged — commit 79b526b62, verified in Dev_new_gui.
The suggested fix was already implemented: _import_from_file does use spec_from_file_location and does
locate the correct file. What failed was exec_module — the plugin's own imports reference plugins.core_plugins.*, and those parent packages exist in no sys.modules. The log read "File-path
fallback failed ... No module named 'plugins.core_plugins'", i.e. the loader reporting it could not load a
file it had already found, which is why the fallback looked broken rather than incomplete.
Each parent now gets a namespace module whose __path__ points at the matching real directory, walked up
from the module file so the hyphen/underscore mapping is derived rather than guessed. An existing real plugins package is never replaced, and a failed exec withdraws what it created.
Also: the fallback hardcoded main.py, so telemetry-prompt-middleware — which declares ...telemetry_prompt_middleware.plugin and ships plugin.py — could never have been found by it.
Measured effect. This alone changed no plugin from failing to loading; it moved two from route 2's error
to route 1's, which is what proved it worked. Combined with #13677 (PR #13952) on the real tree:
Closing this one: its specific defect is fixed and verified end-to-end against the shipped tree. The remaining
two failures are separate defects tracked on #13677.
Activity
fix(deploy): sync plugins/ into the backend tree so core plugins are …
fix(deploy): sync plugins/ into the backend tree so core plugins are …
fix(plugin-loader): annotate _import_from_file return as ModuleType t…
mrveiss commentedon Jun 22, 2026
Deploy half fixed in #10447 (merged): backend role now syncs
code_source/plugins/→backend_code_dir/plugins/, sodiscover_plugins()finds the core plugins (thePlugin directory does not existflood is gone — validated on the box). The import half (file-path fallback for hyphenated dirs) lands via #10442. This issue fully resolves once #10442 merges.feat(integrations): plugin-loader file-path fallback for core-plugins…
github-actions commentedon Jun 22, 2026
PR #10442 (merged to
Dev_new_gui) references this issue with a close keyword.If this issue is fully resolved, close it manually. If work remains, no action is needed.
mrveiss commentedon Jun 22, 2026
Merged to
Dev_new_gui(4d5f464bd). Plugin-loader file-path fallback for core-plugins (hyphen-dir → underscore module) merged; loader now resolves image/video-generation plugins via spec_from_file_location with Plugin alias + BasePlugin fallback. Batch #10440.mrveiss commentedon Aug 7, 2026
Reopening — the file-path fallback added for this issue does not work. Two core plugins still fail to
import on every backend start, observed on
84b88baa1591after a clean host boot.Current failure
The fallback is present and attributed to this issue:
It locates the correct file — the warning names
plugins/core-plugins/image-generation-plugin/main.py,which exists — and then still raises
No module named 'plugins.core_plugins'. So the fallback resolves thepath and then imports by dotted name anyway, which is the exact failure it was meant to bypass.
The underlying mismatch is unchanged
entry_pointuses underscores; the directories use hyphens:Confirmed layout:
Impact
Image generation and video generation are both unavailable, and the failure is quiet — the backend starts
activeand healthy. The log also shows these two plugins reportingloaded with optional env vars unset: ['OPENAI_API_KEY', 'FLUX_API_KEY', 'STABILITY_API_KEY']shortly before the import fails, so a readerskimming the log sees "loaded" and an unrelated-looking import error separately.
Suggested fix
Have the fallback load from the located file —
importlib.util.spec_from_file_locationwith a syntheticmodule name — rather than re-attempting a dotted import. A test that loads every manifest under
plugins/core-plugins/would cover all seven and stop this reopening a third time.Related: the same loader has two further defects filed separately (dependency check consulting the wrong
registry; discovery running twice).
mrveiss commentedon Aug 9, 2026
Part of umbrella #13852
Wave 2 — signal exists, nothing consumes it
Update #13852 when this issue changes state
This issue appears as a checklist item on #13852. Whoever moves it is responsible for the
umbrella staying accurate — the umbrella is the only place the ordering and the shared acceptance
criterion live, so a stale checklist there silently breaks the sequencing for everything else.
not priority.
Why these are grouped
Eleven findings from one diagnostic session sharing a single property: the system was failing and
nothing said so — or something said the opposite. The umbrella's acceptance criterion is the part
no individual child owns:
systemctl is-activereturnedactivethrough four separate incidents in that session.#12460/#13736 is linked on the umbrella as the worked example to copy — metric plus alert rule,
verified end-to-end against the worker's own log for the same synthesis.
mrveiss commentedon Aug 10, 2026
Reproduced on
Dev_new_gui: 7 discovered, 0 loadedDriving the real
PluginLoaderagainst the realplugins/tree:So #13677's headline holds exactly. But it is three distinct causes, not one, and only two of them are
what the issues currently describe. The one that affects the most plugins is not mentioned anywhere.
Route 1 — dual-identity
BasePlugin(4 of 7: logger, mcp-wrapper, hello, kb-event)The module imports fine. The class is there. The loader simply cannot recognise it:
Verified they are different class objects:
issubclassis therefore False and the loader reports "No plugin class found" — an error message that sendsthe reader looking for a missing class that is right there. This is the single largest route and it is
described in neither #10294 nor #13677.
Route 2 — the file-path fallback loads the file, then its own imports fail (2 of 7)
This is #10294's remaining bug, and the umbrella's phrasing is nearly right:
The fallback does locate the file and does use
spec_from_file_location— that part of #10294 isalready implemented. What fails is
exec_module: the plugin's own transitive imports referenceplugins.core_plugins.*, and those parent packages exist nowhere insys.modules. So the fix is not "loadfrom the located file" (already done) but "make the package path resolvable for the module's own imports" —
register synthetic namespace packages for
plugins,plugins.core_plugins, and the plugin dir beforeexec_module.Note the fallback also hardcodes
main.py, whiletelemetry-prompt-middlewaredeclaresentry_point: ...telemetry_prompt_middleware.pluginand shipsplugin.py. The last path segment should drivethe filename.
Route 3 — a missing optional dependency (1 of 7)
Relates to #13677's "dependency check resolves pip packages against the plugin registry".
Why this matches the umbrella
Every route fails silently at the fleet level: nothing emits
loaded N of M, so 0-of-7 and"no plugins installed" are the same observation. Route 1 is worse than silent — it emits a confident error
naming the wrong thing.
Suggested split
exec_module, plus filename from the entrypoint's last segment.
BasePluginidentity, or an identity-tolerant check) and route 3, plus theloaded N of Msignal that makes any of this visible.fix(plugin-sdk): file-path fallback located the plugin file and could…
github-actions commentedon Aug 10, 2026
PR #13944 (merged to
Dev_new_gui) references this issue with a close keyword.If this issue is fully resolved, close it manually. If work remains, no action is needed.
fix(plugin-sdk): 7 plugins failed and it looked like none were instal…
mrveiss commentedon Aug 10, 2026
PR #13944 merged — commit
79b526b62, verified inDev_new_gui.The suggested fix was already implemented:
_import_from_filedoes usespec_from_file_locationand doeslocate the correct file. What failed was
exec_module— the plugin's own imports referenceplugins.core_plugins.*, and those parent packages exist in nosys.modules. The log read "File-pathfallback failed ... No module named 'plugins.core_plugins'", i.e. the loader reporting it could not load a
file it had already found, which is why the fallback looked broken rather than incomplete.
Each parent now gets a namespace module whose
__path__points at the matching real directory, walked upfrom the module file so the hyphen/underscore mapping is derived rather than guessed. An existing real
pluginspackage is never replaced, and a failed exec withdraws what it created.Also: the fallback hardcoded
main.py, sotelemetry-prompt-middleware— which declares...telemetry_prompt_middleware.pluginand shipsplugin.py— could never have been found by it.Measured effect. This alone changed no plugin from failing to loading; it moved two from route 2's error
to route 1's, which is what proved it worked. Combined with #13677 (PR #13952) on the real tree:
Closing this one: its specific defect is fixed and verified end-to-end against the shipped tree. The remaining
two failures are separate defects tracked on #13677.
fix(plugin-sdk): all 7 core plugins failed and it looked like none we…
fix(plugin-sdk): three ways a plugin fails to load with no way to say…