ansible/ansible · error · AnsibleError
this role does not appear to have a valid meta/main.yml file
Error message
this role does not appear to have a valid meta/main.yml file.
What it means
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.
Source
Thrown at lib/ansible/galaxy/role.py:335
if meta_main in member.name:
# Look for parent of meta/main.yml
# Due to possibility of sub roles each containing meta/main.yml
# look for shortest length parent
meta_parent_dir = os.path.dirname(os.path.dirname(member.name))
if not meta_file:
archive_parent_dir = meta_parent_dir
meta_file = member
else:
if len(meta_parent_dir) < len(archive_parent_dir):
archive_parent_dir = meta_parent_dir
meta_file = member
if not meta_file:
raise AnsibleError("this role does not appear to have a meta/main.yml file.")
else:
try:
self._metadata = yaml_load(role_tar_file.extractfile(meta_file))
except Exception:
raise AnsibleError("this role does not appear to have a valid meta/main.yml file.")
paths = self.paths
if self.path != paths[0]:
# path can be passed though __init__
# FIXME should this be done in __init__?
paths[:0] = self.path
paths_len = len(paths)
for idx, path in enumerate(paths):
self.path = path
display.display("- extracting %s to %s" % (self.name, self.path))
try:
if os.path.exists(self.path):
if not os.path.isdir(self.path):
raise AnsibleError("the specified roles path exists and is not a directory.")
elif not context.CLIARGS.get("force", False):
raise AnsibleError("the specified role %s appears to already exist. Use --force to replace it." % self.name)
else:
# using --force, remove the old pathView on GitHub (pinned to 9cf16a4aca)
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
Example fix
# meta/main.yml before (tab indentation) galaxy_info: author: me # after (spaces) galaxy_info: author: me
Defensive patterns
Strategy: validation
Validate before calling
import yaml
def precheck_role_meta_yaml(tar_path, member_name):
with tarfile.open(tar_path) as tf:
text = tf.extractfile(member_name).read()
try:
yaml.safe_load(text)
except yaml.YAMLError as e:
raise SystemExit(f'{member_name} in {tar_path}: invalid YAML: {e}') Try / catch
from ansible.errors import AnsibleError
try:
role.install()
except AnsibleError as e:
if 'valid meta/main.yml' in str(e):
extract_and_show_yaml_error() # surface the underlying YAML problem to the user
raise Prevention
- Never use tabs in YAML; configure your editor to insert spaces for meta files
- Run yamllint on role meta before publishing
When it happens
Trigger: 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.
Common situations: Hand-edited meta files with tabs or mis indentation; templating artifacts ({{ }} leftovers) inside meta; encoding issues (BOM, latin-1 bytes); files truncated during download.
Related errors
- Expected role dependencies to be a list. Role {self} has met
- Must specify name or src for role
- Unable to load data from include requirements file: %s %s
- Invalid offline source info for {namespace}.{name}:{version}
- Invalid version found for the collection '{first_req}': {ver
AI-assisted analysis of ansible/ansible@9cf16a4aca (2026-08-15).
Data as JSON: /api/errors/d1da4943024a2809.
Report an issue: GitHub.