p-e-w/heretic · error · ImportError
Plugin file '{plugin_path}' does not exist
Error message
Plugin file '{plugin_path}' does not exist What it means
The .py path portion of the plugin name (resolved to an absolute path via Path.cwd() if relative) does not exist on disk. load_plugin() raises ImportError before attempting any import so the user gets a clear missing-file message instead of a low-level import traceback.
Source
Thrown at src/heretic/plugin.py:103
raise ValueError(
"You must append the plugin class name to the filepath like this: path/to/plugin.py:ClassName"
)
# File path with explicit class name, e.g. "C:\\path\\plugin.py:MyPlugin".
if ":" in name:
file_path, class_name = name.rsplit(":", 1)
if not file_path.endswith(".py") or not class_name:
raise ValueError(
"File-based plugin must use the form 'path/to/plugin.py:ClassName'"
)
plugin_path = Path(file_path)
if not plugin_path.is_absolute():
plugin_path = Path.cwd() / plugin_path
plugin_path = plugin_path.resolve()
if not plugin_path.is_file():
raise ImportError(f"Plugin file '{plugin_path}' does not exist")
# We're writing directly to the sys.modules dict,
# so the typical restrictions on module names
# (no dots, slashes, etc.) don't apply.
module_name = f"heretic_plugin_{plugin_path}"
# Reuse already-loaded modules to avoid re-executing the plugin on repeated loads.
module = sys.modules.get(module_name)
if module is None:
spec = importlib.util.spec_from_file_location(module_name, plugin_path)
if spec is None or spec.loader is None:
raise ImportError(
f"Could not load plugin '{name}' (invalid module spec)"
)
module = importlib.util.module_from_spec(spec)
# Cache before executing to match normal import semantics and allowView on GitHub (pinned to bedb94ef11)
Solutions
- Check the resolved path printed in the message and fix the file location or the path in the config.
- Use an absolute path to make the plugin independent of the working directory.
- If relative, cd into the expected directory or fix your launcher's cwd.
- Copy/mount the plugin file into the environment (e.g. Docker volume) where heretic runs.
Example fix
# before scorer = "scorers/keyword_rate.py:KeywordRate" # run from repo root only # after scorer = "/opt/myproj/scorers/keyword_rate.py:KeywordRate"
Defensive patterns
Strategy: validation
Validate before calling
from pathlib import Path
def plugin_file_exists(name: str) -> bool:
p = Path(name.rsplit(":", 1)[0])
if not p.is_absolute():
p = Path.cwd() / p
return p.resolve().is_file() Try / catch
try:
cls = load_plugin(name, Scorer)
except ImportError as e:
sys.exit(str(e)) # includes resolved missing path Prevention
- Prefer absolute paths for plugin files.
- Run heretic from the directory your relative paths assume, or fix the cwd in your launcher.
- Verify mounted volumes in containers include the plugin file.
When it happens
Trigger: load_plugin('plugins/missing.py:MyScorer', ...) where plugins/missing.py does not exist; relative path given while running from a different working directory; typo in the path; file deleted or never committed.
Common situations: Running heretic from a different cwd than the config assumes (relative paths resolve against Path.cwd()); Docker containers without the plugin file mounted; renames/moves of the plugin file; case-sensitive filesystems (MyScorer.py vs myscorer.py on Linux).
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- Plugin '{name}' does not export a class named '{class_name}'
- You must append the plugin class name to the filepath like t
- File-based plugin must use the form 'path/to/plugin.py:Class
- Import-based plugin must use the form 'fully.qualified.modul
- Could not load plugin '{name}' (invalid module spec)
AI-assisted analysis of p-e-w/heretic@bedb94ef11 (2026-08-29).
Data as JSON: /api/errors/e4bf357a8d2c72e6.
Report an issue: GitHub.