Introduction

The chgrp failed: failed to look up group error occurs when Ansible tries to set a file's group ownership to a group that doesn't exist on the remote host. This commonly happens with the file, copy, template, and unarchive modules.

The Error

- name: Create config file
  ansible.builtin.copy:
    src: app.conf
    dest: /etc/myapp/app.conf
    owner: myapp
    group: myapp
fatal: [web01]: FAILED! => {"changed": false, "msg": "chgrp failed: failed to
look up group myapp", "path": "/etc/myapp/app.conf"}

Root Cause

Ansible runs chgrp on the remote host to set file group ownership. The error means the specified group doesn't exist on that host. Common causes:

CauseExample
Group not created yetPlaybook sets file group before creating the group
Typo in group namegroup: wwww-data instead of www-data
Different group names across distrosapache (RHEL) vs www-data (Debian)
NIS/LDAP not configuredCentralized group not available on this host
User created without matching groupuseradd -N skips creating private group

Fix 1: Create the Group First

- name: Create application group
  ansible.builtin.group:
    name: myapp
    state: present

- name: Create application user
  ansible.builtin.user:
    name: myapp
    group: myapp
    system: true

- name: Create config file
  ansible.builtin.copy:
    src: app.conf
    dest: /etc/myapp/app.conf
    owner: myapp
    group: myapp

Task order matters — always create groups/users before setting file ownership.

Fix 2: Verify Group Exists

- name: Check if group exists
  ansible.builtin.command: getent group myapp
  register: group_check
  failed_when: false
  changed_when: false

- name: Create group if missing
  ansible.builtin.group:
    name: myapp
    state: present
  when: group_check.rc != 0

Manual Verification on Remote Host

# Check if group exists
getent group myapp
# myapp:x:1001:

# List all groups
cat /etc/group | grep myapp

# Check user's groups
groups myapp
# myapp : myapp wheel

# Detailed user info
id myapp
# uid=1001(myapp) gid=1001(myapp) groups=1001(myapp),10(wheel)

Fix 3: Handle Cross-Platform Group Names

- name: Set platform-specific group
  ansible.builtin.set_fact:
    web_group: "{{ 'www-data' if ansible_os_family == 'Debian' else 'apache' }}"

- name: Deploy web config
  ansible.builtin.template:
    src: vhost.conf.j2
    dest: /etc/httpd/conf.d/mysite.conf
    owner: root
    group: "{{ web_group }}"
    mode: '0644'

Common Group Name Differences

ServiceRHEL/CentOSDebian/Ubuntu
Apacheapachewww-data
Nginxnginxwww-data
PostgreSQLpostgrespostgres
Dockerdockerdocker
Nobodynobodynogroup

Fix 4: Add Users to Groups

# Add user to existing group
sudo usermod -a -G wheel devops

# Verify
groups devops
# devops : devops wheel

id devops
# uid=1001(devops) gid=1001(devops) groups=1001(devops),10(wheel)

With Ansible:

- name: Add deploy user to docker group
  ansible.builtin.user:
    name: deploy
    groups: docker
    append: true  # Don't remove from existing groups

Complete Example: Application Deployment

---
- name: Deploy application with proper ownership
  hosts: app_servers
  become: true
  vars:
    app_user: myapp
    app_group: myapp
    app_dir: /opt/myapp

  tasks:
    - name: Create application group
      ansible.builtin.group:
        name: "{{ app_group }}"
        system: true

    - name: Create application user
      ansible.builtin.user:
        name: "{{ app_user }}"
        group: "{{ app_group }}"
        system: true
        home: "{{ app_dir }}"
        shell: /sbin/nologin

    - name: Create application directories
      ansible.builtin.file:
        path: "{{ item }}"
        state: directory
        owner: "{{ app_user }}"
        group: "{{ app_group }}"
        mode: '0755'
      loop:
        - "{{ app_dir }}"
        - "{{ app_dir }}/config"
        - "{{ app_dir }}/logs"
        - "{{ app_dir }}/data"

    - name: Deploy configuration
      ansible.builtin.template:
        src: app.conf.j2
        dest: "{{ app_dir }}/config/app.conf"
        owner: "{{ app_user }}"
        group: "{{ app_group }}"
        mode: '0640'
      notify: restart myapp

  handlers:
    - name: restart myapp
      ansible.builtin.systemd:
        name: myapp
        state: restarted

Debugging Checklist

  1. Does the group exist? → getent group <name> on remote host
  2. Typo? → Compare group name in playbook vs /etc/group
  3. Task order? → Group creation must come before file operations
  4. Cross-platform? → Use ansible_os_family for conditional group names
  5. LDAP/NIS? → Check nsswitch.conf and network connectivity
  6. SELinux? → Check ls -laZ for SELinux context issues

Conclusion

The chgrp failed error means the group doesn't exist on the remote host. Fix it by creating the group with ansible.builtin.group before any file operations, verify with getent group, and handle cross-platform differences with ansible_os_family conditionals. Always structure playbooks with group/user creation tasks before file ownership tasks.