sqlalchemy/alembic · error · ValueError
Invalid plugin expression
Error message
Invalid plugin expression {name!r} What it means
Raised as ValueError by _make_re (plugins.py:156-166) when a plugin expression in the include_plugins option contains a token that is neither '*' (wildcard) nor a valid Python identifier. The matcher builds a regex per '.'-separated token; a token with hyphens, spaces, or punctuation fails token.isidentifier() and is rejected. This validates the `alembic include_plugins` config option.
Solutions
- Use only valid Python identifiers and '*' in include_plugins, separated by dots (e.g. myplugin or pkg.subplugin or pkg.*).
- Remove any hyphens, spaces, or punctuation from the plugin name in alembic.ini.
- Confirm the plugin's distribution registers it under the exact identifier you wrote.
Example fix
// before (alembic.ini) [alembic] include_plugins = my-plugin // after [alembic] include_plugins = myplugin
Defensive patterns
Strategy: validation
Validate before calling
# Validate an include_plugins expression matches alembic's rules before use.
def valid_plugin_expr(expr: str) -> bool:
for token in expr.split('.'):
if token == '*':
continue
if not token.isidentifier():
return False
return True
for p in include_plugins:
if not valid_plugin_expr(p):
raise ValueError(f'Invalid plugin expression {p!r}; use identifiers and * only') Type guard
def is_valid_plugin_token(token: str) -> bool:
return token == '*' or token.isidentifier() Prevention
- Use only valid Python identifiers and '*' in include_plugins, joined by dots.
- Avoid hyphens, spaces, and punctuation in plugin names in alembic.ini.
- Lint alembic.ini plugin tokens against isidentifier() in CI.
When it happens
Trigger: Setting include_plugins = bad-name! (or any non-identifier token) in alembic.ini, or passing a malformed plugin glob via the API. Each token must be a Python identifier or '*'.
Common situations: Typos in alembic.ini (e.g. include_plugins = my-plugin with a hyphen); copy-pasting a module path with a stray character; mixing wildcard and identifier syntax incorrectly like myplugin.*.extra.
Related errors
- A plugin named is already registered
- Can not set dispatch function for object
- Can't change down_revision on a refresh operation.
- Character(s) ' ' not allowed in revision identifier
- Connection, url, or dialect_name is required.
AI-assisted analysis of sqlalchemy/alembic@5551b5d35f (2026-08-11).
Data as JSON: /api/errors/a3268d2099d94032.
Report an issue: GitHub.
Appendix: source
Thrown at alembic/runtime/plugins.py:166
This exact process is invoked automatically at import time for any
plugin module that is published via the ``alembic.plugins`` entrypoint.
"""
module.setup(Plugin(name))
def _make_re(name: str) -> Pattern[str]:
tokens = name.split(".")
reg = r""
for token in tokens:
if token == "*":
reg += r"\..+?"
elif token.isidentifier():
reg += r"\." + token
else:
raise ValueError(f"Invalid plugin expression {name!r}")
# omit leading r'\.'
return re.compile(f"^{reg[2:]}$")
def _setup() -> None:
# setup third party plugins
for entrypoint in metadata.entry_points(group="alembic.plugins"):
for mod in entrypoint.load():
Plugin.setup_plugin_from_module(mod, entrypoint.name)
_setup()
View on GitHub (pinned to 5551b5d35f)