{"record":{"id":"a3268d2099d94032","repo":"sqlalchemy/alembic","slug":"invalid-plugin-expression-name-r","errorCode":null,"errorMessage":"Invalid plugin expression {name!r}","messagePattern":"Invalid plugin expression (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"alembic/runtime/plugins.py","lineNumber":166,"sourceCode":"\n        This exact process is invoked automatically at import time for any\n        plugin module that is published via the ``alembic.plugins`` entrypoint.\n\n        \"\"\"\n        module.setup(Plugin(name))\n\n\ndef _make_re(name: str) -> Pattern[str]:\n    tokens = name.split(\".\")\n\n    reg = r\"\"\n    for token in tokens:\n        if token == \"*\":\n            reg += r\"\\..+?\"\n        elif token.isidentifier():\n            reg += r\"\\.\" + token\n        else:\n            raise ValueError(f\"Invalid plugin expression {name!r}\")\n\n    # omit leading r'\\.'\n    return re.compile(f\"^{reg[2:]}$\")\n\n\ndef _setup() -> None:\n    # setup third party plugins\n    for entrypoint in metadata.entry_points(group=\"alembic.plugins\"):\n        for mod in entrypoint.load():\n            Plugin.setup_plugin_from_module(mod, entrypoint.name)\n\n\n_setup()\n","sourceCodeStart":148,"sourceCodeEnd":180,"githubUrl":"https://github.com/sqlalchemy/alembic/blob/5551b5d35f985c99cb8f1af2b3c526b050e4c059/alembic/runtime/plugins.py#L148-L180","documentation":"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.","triggerScenarios":"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 '*'.","commonSituations":"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.","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."],"exampleFix":"// before (alembic.ini)\n[alembic]\ninclude_plugins = my-plugin\n// after\n[alembic]\ninclude_plugins = myplugin","handlingStrategy":"validation","validationCode":"# Validate an include_plugins expression matches alembic's rules before use.\ndef valid_plugin_expr(expr: str) -> bool:\n    for token in expr.split('.'):\n        if token == '*':\n            continue\n        if not token.isidentifier():\n            return False\n    return True\n\nfor p in include_plugins:\n    if not valid_plugin_expr(p):\n        raise ValueError(f'Invalid plugin expression {p!r}; use identifiers and * only')","typeGuard":"def is_valid_plugin_token(token: str) -> bool:\n    return token == '*' or token.isidentifier()","tryCatchPattern":null,"preventionTips":["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."],"tags":["alembic","plugins","configuration","validation"],"backgroundTag":null,"analyzedSha":"5551b5d35f985c99cb8f1af2b3c526b050e4c059","analyzedAt":"2026-08-11T01:38:46.612Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}