Ansible Lint
raw JSON → 26.4.0 verified Wed May 13 auth: no python
Ansible Lint is a command-line tool that checks Ansible playbooks, roles, and collections for practices and behavior that could potentially be improved. It helps maintain code quality, enforce best practices, and identify common pitfalls in Ansible automation. The current version is 26.4.0, and it maintains an active release cadence, often with multiple updates per month to incorporate new rules and keep pace with Ansible Core development.
pip install ansible-lint Common errors
error Couldn't parse task at playbook.yml:6 (conflicting action statements: debug, __line__ ↓
cause This error occurs when a task in the playbook has conflicting action statements, leading to parsing issues.
fix
Ensure that each task in your playbook has a single, clear action statement without conflicts.
error syntax-check[unknown-module]: couldn't resolve module/action ↓
cause This error indicates that Ansible-lint cannot resolve a module or action, possibly due to missing or uninstalled collections or roles.
fix
Ensure all required collections and roles are listed in a 'requirements.yml' file and installed properly.
error internal-error: An internal error occurred while processing the file ↓
cause This error can be caused by internal bugs or issues within custom rules, leading to processing failures.
fix
Review the detailed error message provided, check for issues in custom rules, and consider adding the 'internal-error' rule to the 'warn_list' until resolved.
error ignore-errors: Tasks should not use 'ignore_errors' directive ↓
cause Using 'ignore_errors: true' in tasks can hide actual failures and lead to unexpected behavior.
fix
Instead of 'ignore_errors', use 'register' to capture errors and 'failed_when' to specify acceptable error conditions.
error avoid-implicit[copy-content]: 'content' should be a string ↓
cause The 'content' parameter in the 'copy' module is not a string, which can lead to unexpected behavior.
fix
Use explicit Jinja templating to convert the content to a string, e.g., 'content: "{{ content | to_json }}"'.
Warnings
breaking `ansible-lint` versions `23.x` and newer require Python `3.10` or later. Users on older Python versions (e.g., 3.8, 3.9) will encounter installation or runtime errors and must upgrade their Python environment or use an older `ansible-lint` version. ↓
fix Upgrade your Python environment to 3.10+ or pin `ansible-lint<23.0.0`.
breaking Major `ansible-lint` releases (e.g., 6.x, 23.x) frequently introduce new rule IDs, rename existing ones, and modify the set of rules enabled by default. This can cause previously passing playbooks to fail lint checks or require updates to custom `.ansible-lint` configurations to suppress/enable specific rules. ↓
fix Review the release notes for rule changes when upgrading. Update your `.ansible-lint` configuration to adjust enabled/disabled rules as needed, or explicitly specify `--strict-annotations` to enforce comments.
gotcha The schema and available options within the `.ansible-lint` configuration file are subject to change between versions. Using a configuration file from an older `ansible-lint` version with a newer installation can lead to ignored settings, warnings about unknown options, or unexpected linting behavior. ↓
fix Always review the configuration documentation for your specific `ansible-lint` version when upgrading. Regenerate or carefully adapt existing configuration files.
gotcha While `ansible-lint` offers a Python API (e.g., `ansiblelint.app.App`, `ansiblelint.runner.Runner`), its public interface is not as strictly stable as its CLI. Direct programmatic usage should be thoroughly tested after each `ansible-lint` upgrade, as internal changes might affect custom integrations. ↓
fix Pin `ansible-lint` to a specific version for programmatic integrations and perform thorough regression testing when upgrading to a new major or minor version.
Install compatibility last tested: 2026-05-13 v6.22.2 installed · v26.4.0 latest
python os / libc status wheel install import disk mem side effects
3.10 alpine (musl) wheel - 0.35s 68.4M 9.1M clean
3.10 alpine (musl) - - 0.49s 67.3M 9.1M -
3.10 slim (glibc) wheel 6.9s 0.24s 75M 9.1M clean
3.10 slim (glibc) - - 0.31s 73M 9.1M -
3.11 alpine (musl) wheel - 0.62s 78.3M 10.5M clean
3.11 alpine (musl) - - 0.76s 77.2M 10.4M -
3.11 slim (glibc) wheel 6.5s 0.57s 84M 10.5M clean
3.11 slim (glibc) - - 0.66s 83M 10.4M -
3.12 alpine (musl) wheel - 0.70s 68.9M 11.2M clean
3.12 alpine (musl) - - 1.82s 67.8M 11.2M -
3.12 slim (glibc) wheel 5.8s 0.75s 75M 11.2M clean
3.12 slim (glibc) - - 1.05s 74M 11.2M -
3.13 alpine (musl) wheel - 0.70s 68.5M 11.4M clean
3.13 alpine (musl) - - 1.04s 67.3M 11.4M -
3.13 slim (glibc) wheel 5.9s 0.74s 75M 11.4M clean
3.13 slim (glibc) - - 1.25s 74M 11.4M -
3.9 alpine (musl) wheel - 0.43s 78.8M 12.2M clean
3.9 alpine (musl) - - 0.57s 77.7M 12.2M -
3.9 slim (glibc) wheel 9.0s 0.38s 84M 12.2M clean
3.9 slim (glibc) - - 0.65s 83M 12.2M -
Imports
- App
from ansiblelint.app import App - Options
from ansiblelint.config import Options - MatchError
from ansiblelint.errors import MatchError
Quickstart last tested: 2026-04-25
import os
import tempfile
from pathlib import Path
from ansiblelint.app import App
from ansiblelint.config import Options
# Create a temporary playbook file for linting
playbook_content = """
---
- name: Example playbook with common linting issues
hosts: localhost
tasks:
- name: Using command module directly (LINT: no-shell-command)
ansible.builtin.command: echo "hello world"
- name: Insecure default permissions for file (LINT: risky-file-permissions)
ansible.builtin.file:
path: /tmp/testfile.txt
state: touch
mode: "0777" # Risky permissions
"""
temp_dir = Path(tempfile.mkdtemp())
playbook_path = temp_dir / "playbook.yml"
with open(playbook_path, "w") as f:
f.write(playbook_content)
try:
# Configure linting options
options = Options()
# Prevent App from configuring logging globally, for cleaner output in example
options.configure_logger = False
# Specify the file(s) to lint
options.lintables = [str(playbook_path)]
# Set up app and run lint
app = App(options)
matches = app.run()
print(f"Linting results for {playbook_path.name}:")
if matches:
for match in matches:
print(f"- [{match.rule_id}] {match.message} (File: {match.filename}, Line: {match.linenumber})")
else:
print("No linting issues found.")
except Exception as e:
print(f"An error occurred: {e}")
finally:
# Clean up the temporary directory and file
if temp_dir.exists():
for item in temp_dir.iterdir():
item.unlink()
temp_dir.rmdir()