Version:
revision: 6320e157a22f47d0dad42f84e8ee58b06aa5db3f
timestamp: 1774653761
ver_maj: 3
ver_min: 2
ver_patch: 0
ver_pre: 6320e157a-dirty
dirty: true
debug: false
Fresh install on Rocky 8 failed configuring the Kernel via Ansible.
fatal: [localhost]: FAILED! =>
msg: 'Unexpected templating type error occurred on ({{ (state | default(''present'') == ''absent'') | ternary(''Removing'', ''Adding'') }} {{ item.key }}{{ (state | default(''present'') == ''absent'') | ternary('''', '' => '' + item.value) }}): must be str, not NoneType'
Fixing the loop solved that error:
loop_control:
label: "{{ (state | default('present') == 'absent') | ternary('Removing', 'Adding') }} {{ item.key }}{{ (state | default('present') == 'absent') | ternary('', ' => ' + (item.value | string)) }}"
Then it failed with a grub issue, turns out the regex / replace was corrupting line 6 of /etc/default/grub
fatal: [localhost]: FAILED! => changed=true
cmd:
- /usr/sbin/grub2-mkconfig
- -o
- /etc/grub2.cfg
delta: '0:00:00.195315'
end: '2026-03-29 19:34:24.767710'
msg: non-zero return code
rc: 2
start: '2026-03-29 19:34:24.572395'
stderr: '/etc/default/grub: line 7: unexpected EOF while looking for matching `"'''
stderr_lines: <omitted>
stdout: ''
stdout_lines: <omitted>
$] cat /etc/default/grub
GRUB_TIMEOUT=5
GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)"
GRUB_DEFAULT=saved
GRUB_DISABLE_SUBMENU=true
GRUB_TERMINAL_OUTPUT="console"
GRUB_CMDLINE_LINUX="resume=UUID=c613f83b-c875-487f-9039-b6c4d623468d rootflags=usrquota,grpquota,prjquota" systemd.unified_cgroup_hierarchy=1"
GRUB_DISABLE_RECOVERY="true"
GRUB_ENABLE_BLSCFG=true
Line 6 should be:
GRUB_CMDLINE_LINUX="resume=UUID=c613f83b-c875-487f-9039-b6c4d623468d rootflags=usrquota,grpquota,prjquota systemd.unified_cgroup_hierarchy=1"
The regex inserted systemd.unified_cgroup_hierarchy=1 outside the closing quote instead of inside it.
At this point, I’m not a regex expert and brought in Claude to assist. While this is by no means a perfect solution, it did allow my installation to complete.
- name: Set kernel flags (strip existing value)
replace:
path: "{{ kernel_boot_cmdline }}"
regexp: '{{ regex_preamble }}\s+{{ item.key | regex_escape }}=[^"''\s]+'
replace: '\1'
loop_control:
label: "Stripping {{ item.key }}"
with_dict: "{{ options | default({ option | default(omit): value | default(None)}) }}"
when: not (rootflags | default(False))
- name: Set kernel flags (append if present)
replace:
path: "{{ kernel_boot_cmdline }}"
regexp: '{{ regex_preamble }}([''"])(.*?)(\2\s*)$'
replace: '\1\2\3 {{ item.key }}={{ item.value | string }}\4'
loop_control:
label: "Adding {{ item.key }}={{ item.value }}"
with_dict: "{{ options | default({ option | default(omit): value | default(None)}) }}"
when:
- not (rootflags | default(False))
- state | default('present') == 'present'
notify: Update grub
FWIW, this was the justification provided:
The key insight: one regex cannot reliably both consume and re-emit the closing quote when it’s also optional. Splitting strip and append into two tasks eliminates the problem entirely.