{"record":{"id":"d1da4943024a2809","repo":"ansible/ansible","slug":"this-role-does-not-appear-to-have-a-valid-meta-mai","errorCode":null,"errorMessage":"this role does not appear to have a valid meta/main.yml file.","messagePattern":"this role does not appear to have a valid meta/main\\.yml file\\.","errorType":"exception","errorClass":"AnsibleError","httpStatus":null,"severity":"error","filePath":"lib/ansible/galaxy/role.py","lineNumber":335,"sourceCode":"                        if meta_main in member.name:\n                            # Look for parent of meta/main.yml\n                            # Due to possibility of sub roles each containing meta/main.yml\n                            # look for shortest length parent\n                            meta_parent_dir = os.path.dirname(os.path.dirname(member.name))\n                            if not meta_file:\n                                archive_parent_dir = meta_parent_dir\n                                meta_file = member\n                            else:\n                                if len(meta_parent_dir) < len(archive_parent_dir):\n                                    archive_parent_dir = meta_parent_dir\n                                    meta_file = member\n                if not meta_file:\n                    raise AnsibleError(\"this role does not appear to have a meta/main.yml file.\")\n                else:\n                    try:\n                        self._metadata = yaml_load(role_tar_file.extractfile(meta_file))\n                    except Exception:\n                        raise AnsibleError(\"this role does not appear to have a valid meta/main.yml file.\")\n\n                paths = self.paths\n                if self.path != paths[0]:\n                    # path can be passed though __init__\n                    # FIXME should this be done in __init__?\n                    paths[:0] = self.path\n                paths_len = len(paths)\n                for idx, path in enumerate(paths):\n                    self.path = path\n                    display.display(\"- extracting %s to %s\" % (self.name, self.path))\n                    try:\n                        if os.path.exists(self.path):\n                            if not os.path.isdir(self.path):\n                                raise AnsibleError(\"the specified roles path exists and is not a directory.\")\n                            elif not context.CLIARGS.get(\"force\", False):\n                                raise AnsibleError(\"the specified role %s appears to already exist. Use --force to replace it.\" % self.name)\n                            else:\n                                # using --force, remove the old path","sourceCodeStart":317,"sourceCodeEnd":353,"githubUrl":"https://github.com/ansible/ansible/blob/9cf16a4aca7898481c257f1e17ad28d0b67b1f85/lib/ansible/galaxy/role.py#L317-L353","documentation":"Raised in Role.install (lib/ansible/galaxy/role.py:335) when the meta/main.yml member was found but YAML parsing of it raised any Exception. This indicates the metadata file exists yet is syntactically invalid YAML (or unreadable), so the role's metadata cannot be loaded.","triggerScenarios":"Installing a role whose meta/main.yml contains YAML syntax errors (tabs, bad indentation, duplicate keys with strict loaders) — yaml_load throws and the generic except converts it to this AnsibleError.","commonSituations":"Hand-edited meta files with tabs or mis indentation; templating artifacts ({{ }} leftovers) inside meta; encoding issues (BOM, latin-1 bytes); files truncated during download.","solutions":["Validate locally: `python -c \"import yaml; yaml.safe_load(open('meta/main.yml'))\"` and fix the reported line/column","Replace tabs with spaces and fix indentation under galaxy_info/dependencies","If third-party, report to the author or pin the last known-good version of the role"],"exampleFix":"# meta/main.yml before (tab indentation)\ngalaxy_info:\n\tauthor: me\n\n# after (spaces)\ngalaxy_info:\n  author: me","handlingStrategy":"validation","validationCode":"import yaml\n\ndef precheck_role_meta_yaml(tar_path, member_name):\n    with tarfile.open(tar_path) as tf:\n        text = tf.extractfile(member_name).read()\n    try:\n        yaml.safe_load(text)\n    except yaml.YAMLError as e:\n        raise SystemExit(f'{member_name} in {tar_path}: invalid YAML: {e}')","typeGuard":null,"tryCatchPattern":"from ansible.errors import AnsibleError\ntry:\n    role.install()\nexcept AnsibleError as e:\n    if 'valid meta/main.yml' in str(e):\n        extract_and_show_yaml_error()  # surface the underlying YAML problem to the user\n    raise","preventionTips":["Never use tabs in YAML; configure your editor to insert spaces for meta files","Run yamllint on role meta before publishing"],"tags":["roles","yaml","metadata","parsing"],"backgroundTag":null,"analyzedSha":"9cf16a4aca7898481c257f1e17ad28d0b67b1f85","analyzedAt":"2026-08-15T00:15:47.100Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}