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 things

View on GitHub (pinned to 9cf16a4aca)

Solutions

  1. Open the file at the origin line/column given in the error obj and fix the syntax error.
  2. Sanity-check it locally: `python -m py_compile <module_file>` or `python -c "import ast; ast.parse(open('<file>').read())"`.
  3. If a merge/install corrupted the file, re-checkout or reinstall the collection.
  4. 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

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


AI-assisted analysis of ansible/ansible@9cf16a4aca (2026-08-15). Data as JSON: /api/errors/5e3cb95177670fff. Report an issue: GitHub.