ansible/ansible · error · AnsibleError
Unable to compile {module_name!r}.
Error message
Unable to compile {module_name!r}. What it means
Raised in _compile_module_ast: the module's Python source failed to parse into an AST (compile with PyCF_ONLY_AST raised SyntaxError). The error's obj is the source Origin with the failing line/column, so the reported position identifies the exact syntax error in the module file.
Source
Thrown at lib/ansible/executor/module_common.py:1005
if not parent.name:
continue
p_init = str(parent / '__init__.py')
if p_init not in written_files:
display.vvvvv(f"Including parent init file {p_init}")
zf.writestr(_make_zinfo(p_init, date_time, zf=zf), b'')
written_files.add(p_init)
return module_metadata
def _compile_module_ast(module_name: str, source_code: str | bytes) -> ast.Module:
origin = Origin.get_tag(source_code) or Origin.UNKNOWN
# compile the source, process all relevant imported modules
try:
tree = t.cast(ast.Module, compile(source_code, str(origin), 'exec', ast.PyCF_ONLY_AST))
except SyntaxError as ex:
raise AnsibleError(f"Unable to compile {module_name!r}.", obj=origin.replace(line_num=ex.lineno, col_num=ex.offset)) from ex
return tree
def _is_binary(b_module_data):
"""Heuristic to classify a file as binary by sniffing a 1k header; see https://stackoverflow.com/a/7392391"""
textchars = bytearray(set([7, 8, 9, 10, 12, 13, 27]) | set(range(0x20, 0x100)) - set([0x7f]))
start = b_module_data[:1024]
return bool(start.translate(None, textchars))
def _get_ansible_module_fqn(module_path):
"""
Get the fully qualified name for an ansible module based on its pathname
remote_module_fqn is the fully qualified name. Like ansible.modules.system.ping
Or ansible_collections.Namespace.Collection_name.plugins.modules.ping
.. warning:: This function is for ansible modules only. It won't work for other thingsView on GitHub (pinned to 9cf16a4aca)
Solutions
- Open the file at the origin line/column given in the error obj and fix the syntax error.
- Sanity-check it locally: `python -m py_compile <module_file>` or `python -c "import ast; ast.parse(open('<file>').read())"`.
- If a merge/install corrupted the file, re-checkout or reinstall the collection.
- Ensure the module's Python syntax is compatible with the controller's Python version.
Example fix
# before (module.py, line 12)
def run():
return {
'a': 1
# after
def run():
return {
'a': 1,
} Defensive patterns
Strategy: validation
Validate before calling
import ast
def module_parses(path: str) -> tuple[bool, str]:
try:
ast.parse(open(path, 'rb').read(), filename=path)
return True, ''
except SyntaxError as ex:
return False, f'{path}:{ex.lineno}:{ex.offset}: {ex.msg}'
# use in pre-commit / CI over changed module files Try / catch
try:
compile_or_package()
except AnsibleError as ex:
if 'Unable to compile' in str(ex):
# ex.obj is the Origin with line_num/col_num of the syntax error
origin = ex.obj
open_editor(origin.path, origin.line_num) Prevention
- Run `python -m py_compile` or compileall over modules in pre-commit hooks.
- Run ansible-test sanity on collections, which includes compile checks for all modules.
- Match your modules' syntax level to the controller's Python version.
When it happens
Trigger: Any Python module (or transitively scanned module_utils source) containing a syntax error — invalid syntax, bad indentation, unterminated literal — is packaged by the controller; compile() raises SyntaxError which is wrapped with module name and origin position.
Common situations: Editing a module and introducing a syntax error; a mangled file from a bad git merge; Python 3.x-only syntax used where the controller's parser rejects it; files truncated during copy/install; encoding issues producing garbage bytes.
Related errors
- string cannot be converted to a dict, must either be a JSON
- Something wrong with this module zip file: should not contai
- Missing base YAML definition file (bad install?): %s
- Module METADATA schema_version {schema_version} is unknown.
- Module METADATA is invalid.
AI-assisted analysis of ansible/ansible@9cf16a4aca (2026-08-15).
Data as JSON: /api/errors/5e3cb95177670fff.
Report an issue: GitHub.