{"record":{"id":"5e3cb95177670fff","repo":"ansible/ansible","slug":"unable-to-compile-module-name-r","errorCode":null,"errorMessage":"Unable to compile {module_name!r}.","messagePattern":"Unable to compile (.+?)\\.","errorType":"exception","errorClass":"AnsibleError","httpStatus":null,"severity":"error","filePath":"lib/ansible/executor/module_common.py","lineNumber":1005,"sourceCode":"                if not parent.name:\n                    continue\n                p_init = str(parent / '__init__.py')\n                if p_init not in written_files:\n                    display.vvvvv(f\"Including parent init file {p_init}\")\n                    zf.writestr(_make_zinfo(p_init, date_time, zf=zf), b'')\n                    written_files.add(p_init)\n\n    return module_metadata\n\n\ndef _compile_module_ast(module_name: str, source_code: str | bytes) -> ast.Module:\n    origin = Origin.get_tag(source_code) or Origin.UNKNOWN\n\n    # compile the source, process all relevant imported modules\n    try:\n        tree = t.cast(ast.Module, compile(source_code, str(origin), 'exec', ast.PyCF_ONLY_AST))\n    except SyntaxError as ex:\n        raise AnsibleError(f\"Unable to compile {module_name!r}.\", obj=origin.replace(line_num=ex.lineno, col_num=ex.offset)) from ex\n\n    return tree\n\n\ndef _is_binary(b_module_data):\n    \"\"\"Heuristic to classify a file as binary by sniffing a 1k header; see https://stackoverflow.com/a/7392391\"\"\"\n    textchars = bytearray(set([7, 8, 9, 10, 12, 13, 27]) | set(range(0x20, 0x100)) - set([0x7f]))\n    start = b_module_data[:1024]\n    return bool(start.translate(None, textchars))\n\n\ndef _get_ansible_module_fqn(module_path):\n    \"\"\"\n    Get the fully qualified name for an ansible module based on its pathname\n\n    remote_module_fqn is the fully qualified name.  Like ansible.modules.system.ping\n    Or ansible_collections.Namespace.Collection_name.plugins.modules.ping\n    .. warning:: This function is for ansible modules only.  It won't work for other things","sourceCodeStart":987,"sourceCodeEnd":1023,"githubUrl":"https://github.com/ansible/ansible/blob/9cf16a4aca7898481c257f1e17ad28d0b67b1f85/lib/ansible/executor/module_common.py#L987-L1023","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"# before (module.py, line 12)\ndef run():\n    return {\n        'a': 1\n\n# after\ndef run():\n    return {\n        'a': 1,\n    }","handlingStrategy":"validation","validationCode":"import ast\n\ndef module_parses(path: str) -> tuple[bool, str]:\n    try:\n        ast.parse(open(path, 'rb').read(), filename=path)\n        return True, ''\n    except SyntaxError as ex:\n        return False, f'{path}:{ex.lineno}:{ex.offset}: {ex.msg}'\n\n# use in pre-commit / CI over changed module files","typeGuard":null,"tryCatchPattern":"try:\n    compile_or_package()\nexcept AnsibleError as ex:\n    if 'Unable to compile' in str(ex):\n        # ex.obj is the Origin with line_num/col_num of the syntax error\n        origin = ex.obj\n        open_editor(origin.path, origin.line_num)","preventionTips":["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."],"tags":["ansible","syntax-error","packaging","python"],"backgroundTag":null,"analyzedSha":"9cf16a4aca7898481c257f1e17ad28d0b67b1f85","analyzedAt":"2026-08-15T00:15:47.100Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}