Troubleshoot and Debug Podman Quadlet

Tested on Red Hat Enterprise Linux 10.2 (Coughlan)
Package podman-5.8.2-5.el10_2.x86_64
Applies to Any Linux host with Podman 4.6+ and systemd
Privilege sudo for rootful examples; normal user with systemctl --user for rootless checks
Scope Layered Quadlet debugging — unit not found, search paths, generator dry-run, QUADLET_UNIT_DIRS, unsupported directives, systemd-analyze verify, mandatory daemon-reload, SourcePath, generated-unit warnings, journal reading, oneshot semantics, boot enablement signals, and rootless linger routing. Absorbs unit-not-found recovery. Does not reteach enable mechanics, .pod restart traps, volume permissions, network fixes, or rootless setup.
Related guides Podman Quadlet CLI

Your Quadlet source file exists, but systemctl start says the unit is missing — or the service starts and immediately fails with no obvious container. Before you reach for podman logs, decide which layer broke. Generator, systemd, and Podman each fail differently, and fixing the wrong layer wastes time.


Start by identifying which layer failed

Walk the stack from source file to running container:

text
Quadlet source on disk?
Generator parsed it?
.service unit generated?
systemd loaded the service?
Podman command succeeded?
Container or resource healthy?

If no .service was generated, podman logs cannot help — nothing reached Podman yet. If the unit exists but ExecStart fails, journal and manual podman run checks belong on this page. Deeper runtime topics (ports, volumes, networks) have dedicated guides linked inline.


Error: Unit ... service not found

This is the signature failure when systemd has no web.service in the active manager.

Try to start it:

bash
sudo systemctl start web.service

Sample output:

output
Failed to start web.service: Unit web.service not found.

Rootless users see the same wording under the user manager:

bash
systemctl --user start web.service

Work through the checks below before assuming Podman is broken.

Is the Quadlet in a valid search path?

Rootful units belong under:

text
/etc/containers/systemd/

Rootless units belong under the owning user's config tree:

text
~/.config/containers/systemd/

Administrators may also place user units under /etc/containers/systemd/users/ or /etc/containers/systemd/users/${UID}/. See Rootless Podman Quadlet for path detail — this page only verifies the file is where the generator expects it.

Is the extension correct?

Available Quadlet types depend on Podman version. Podman 5.8.2 recognizes typed suffixes such as:

text
web.container
app.kube
app.pod
data.volume
app.network
web.build
base.image
data.artifact

Older Podman releases may not support every suffix — .build, .pod, and especially .artifact arrived in later versions. A file named web.service or web.txt in the directory will not produce a Quadlet unit.

Did you reload systemd?

After adding or moving a Quadlet file:

bash
sudo systemctl daemon-reload

Rootless:

bash
systemctl --user daemon-reload

Without reload, systemd may never invoke the Podman generator for the new source.

Did the generator reject the file?

When path, extension, and reload look correct but the unit is still missing, run the generator directly — covered in the next section.


Find the generator binary on your host

Paths vary by distribution packaging. Discover what your podman RPM installed:

bash
rpm -ql podman | grep -E 'quadlet|generator'

On RHEL 10.2 the lab host exposes:

output
/usr/libexec/podman/quadlet
/usr/lib/systemd/system-generators/podman-system-generator
/usr/lib/systemd/user-generators/podman-user-generator

podman-system-generator and podman-user-generator are symlinks to /usr/libexec/podman/quadlet. Upstream documentation often shows the generator path under system-generators; on this build the real binary is /usr/libexec/podman/quadlet.

Confirm flags:

bash
/usr/libexec/podman/quadlet --help

Sample output:

output
-dryrun
    	Run in dryrun mode printing debug information
  -user
    	Run as systemd user

Use that binary for the dry-run examples below.


Run the Quadlet generator manually

Dry-run prints translated units without touching systemd. For rootful debugging:

bash
/usr/libexec/podman/quadlet -dryrun

Rootless generator logic:

bash
/usr/libexec/podman/quadlet -user -dryrun

A healthy single-unit source produces a ---web.service--- block and an ExecStart= line you can read immediately.


Isolate sources with QUADLET_UNIT_DIRS

System-wide dry-run noise from dozens of installed units makes one bad file hard to spot. Copy only the suspect Quadlet into a clean directory:

bash
mkdir /tmp/quadlet-debug
cp web.container /tmp/quadlet-debug/

Run the generator against that directory alone:

bash
QUADLET_UNIT_DIRS=/tmp/quadlet-debug /usr/libexec/podman/quadlet -dryrun

Sample output:

output
quadlet-generator[252717]: Loading source unit file /tmp/quadlet-debug/web.container
---web.service---
[X-Container]
Image=quay.io/podman/hello
ContainerName=debug-hello
...
ExecStart=/usr/bin/podman run --name debug-hello ...

Rootless:

bash
QUADLET_UNIT_DIRS=/tmp/quadlet-debug /usr/libexec/podman/quadlet -user -dryrun

QUADLET_UNIT_DIRS is one of the fastest ways to prove whether a single source file parses — without unrelated generator errors from other Quadlets on the host.


Detect unsupported directives from a newer Podman

A .container copied from Podman 6 docs may reference keys your installed generator does not understand. Add a deliberate bad key to see the error shape:

ini
[Container]
Image=quay.io/podman/hello
UnsupportedDirective=foo

Dry-run:

bash
QUADLET_UNIT_DIRS=/tmp/quadlet-debug /usr/libexec/podman/quadlet -dryrun

Sample output:

output
quadlet-generator[252952]: converting "bad.container": unsupported key 'UnsupportedDirective' in group 'Container' in /tmp/quadlet-debug/bad.container
quadlet-generator[252952]: processing encountered some errors

The generator may still emit other valid units in the same run, but the named file will not produce a service. Check your package before blaming a typo:

bash
podman --version

Sample output:

output
podman version 5.8.2

Version skew is a common reason a unit never appears — especially when playbooks pin an older Podman on the host but pull unit files from newer documentation.


Use systemd-analyze verify

Generator dry-run answers Quadlet translation. systemd-analyze verify answers whether the generated systemd unit is structurally valid once generators have run.

After daemon-reload, verify the generated unit file path:

bash
systemd-analyze verify /run/systemd/generator/web.service

A clean check exits silently on the lab host. Rootless:

bash
systemd-analyze --user --generators=true verify /run/user/1014/systemd/generator/web.service

You can also enable generators during verify:

bash
systemd-analyze --generators=true verify web.service
Tool Finds
quadlet -dryrun Bad Quadlet keys, missing sections, unsupported types
systemd-analyze verify Invalid unit syntax, broken dependencies in the generated .service

Use both when a unit fails to load or start.


Reload systemd after every Quadlet change

A recurring mistake: edit web.container, then immediately:

bash
sudo systemctl restart web.service

without reloading. systemd warns when the source changed on disk:

output
Warning: The unit file, source configuration file or drop-ins of web.service changed on disk. Run 'systemctl daemon-reload' to reload units.

The loaded ExecStart may still reference the old container name until you reload. Correct workflow:

bash
sudo systemctl daemon-reload
sudo systemctl restart web.service

Rootless:

bash
systemctl --user daemon-reload
systemctl --user restart web.service

Do not rely on reboot during normal editing — reload is the routine step.


Find the source Quadlet for a generated service

When several similarly named units exist, ask systemd which source file produced the unit:

bash
systemctl show -p SourcePath web.service

Sample output:

output
SourcePath=/etc/containers/systemd/web.container

Rootless:

bash
systemctl --user show -p SourcePath web.service

Sample output:

output
SourcePath=/home/podtest/.config/containers/systemd/web.container

Compare with the generated unit:

bash
systemctl cat web.service

Sample output:

output
# /run/systemd/generator/web.service
# Automatically generated by /usr/lib/systemd/system-generators/podman-system-generator
[X-Container]
Image=quay.io/podman/hello
...
ExecStart=/usr/bin/podman run --name debug-hello-v2 ...

SourcePath points at the editable Quadlet. systemctl cat shows the generated service including [Unit] wiring — never edit files under /run/systemd/generator/ or /run/user/.../systemd/generator/ directly.


Never edit the generated .service

Generator output is ephemeral. Changes under:

text
/run/systemd/generator/
/run/user/$UID/systemd/generator/

disappear on the next daemon-reload. Fix the Quadlet source (*.container, *.pod, *.volume, …) or add a systemd drop-in, then reload.


Read systemd service errors

Once a unit exists, start with status:

bash
systemctl status web.service --no-pager

Sample output:

output
● web.service
     Loaded: loaded (/etc/containers/systemd/web.container; generated)
     Active: active (running) since Sun 2026-08-23 03:30:09 IST; 43ms ago
   Main PID: 253435 (conmon)

Pull the journal for this boot:

bash
journalctl -u web.service -b --no-pager -n 8

Rootless status uses the user manager:

bash
systemctl --user status web.service --no-pager

User-scoped journal for the same unit:

bash
journalctl --user -u web.service --no-pager -n 8

Read the log for the failure class:

  • image pull errors or registry timeouts
  • port already allocated
  • mount or permission denied on volumes
  • executable exited immediately
  • start job timed out

Route port and volume failures to Podman port mapping and volume permission guides when the journal names those resources.


Generated service exists but no container appears

Inspect what systemd actually runs:

bash
systemctl show -p ExecStart web.service

Sample output:

output
ExecStart={ path=/usr/bin/podman ; argv[]=/usr/bin/podman run --name debug-hello-v2 --replace --rm ... ; ... }

Copy the podman run arguments into a manual test only to isolate the failure — do not leave a bypass script in production. If ExecStart never ran, the problem is still systemd ordering or timeouts, not Podman runtime.


Service times out while pulling an image

A .container or .kube service can exceed systemd's normal startup timeout while Podman pulls or builds an image. Raise TimeoutStartSec= in [Service] or pre-pull the image. Resource Quadlets such as .build and .image are oneshot units on Podman 5.8.2 and do not use the same default startup-timeout behavior.

ini
[Service]
TimeoutStartSec=900

Or pre-pull the image before enabling the unit. The journal usually shows pull progress stopping mid-stream when timeout is the culprit.


Service is inactive (dead) but the resource exists

Oneshot Quadlet types — .volume, .network, .build, .image, .artifact — often finish prep work and exit.

Start a volume unit:

bash
sudo systemctl start data-volume.service

Check status:

bash
systemctl status data-volume.service --no-pager

Sample output:

output
● data-volume.service
     Loaded: loaded (/etc/containers/systemd/data.volume; generated)
     Active: active (exited) since Sun 2026-08-23 03:30:27 IST; 32ms ago
    Process: 253771 ExecStart=/usr/bin/podman volume create --ignore systemd-data (code=exited, status=0/SUCCESS)

Verify the Podman object:

bash
podman volume ls

Sample output:

output
local       systemd-data

Resource Quadlets are oneshot services, so they do not represent a continuously running process. Depending on the generated unit, you may see active (exited) or a completed/inactive state. Check Result=success, the command exit status, the journal, and whether the Podman resource exists before treating the state as a failure.


Quadlet service is not enabled at boot

Do not run:

bash
systemctl enable web.service

on a generated transient unit when enablement should come from the Quadlet source:

ini
[Install]
WantedBy=multi-user.target

After adding or changing [Install], reload systemd. Full enable and target wiring lives in Podman Quadlet with systemd — here you only confirm the section exists before chasing generator errors.

Rootless boot persistence also needs linger — see Rootless Podman Quadlet rather than repeating setup on this page.


Container exists with unexpected systemd- name

List containers:

bash
podman ps -a --format '{{.Names}}'

Quadlet defaults to systemd-<unit> unless you set ContainerName= in the [Container] section. That naming is documented behavior, not a generator bug. Set ContainerName= when downstream scripts expect a fixed name — see Podman Quadlet container file.


Dependencies start in the wrong order

Inspect ordering:

bash
systemctl list-dependencies web.service --no-pager

Sample output:

output
web.service
● ├─network-online.target
● │ └─NetworkManager-wait-online.service

Read generated After= and Requires= in:

bash
systemctl cat web.service

Ordering guarantees start sequence — not application readiness inside the container. Prefer HealthCmd, Notify=, or explicit After= on image or volume units instead of sleep in ExecStartPre.


Rootless unit works until logout

When a user unit stops after the last SSH session ends, linger is the usual cause. Check:

bash
loginctl show-user podtest -p Linger

Sample output:

output
Linger=yes

Linger=no means the user manager may disappear on logout. Full linger workflow: Rootless Podman Quadlet.


Debug checklist

Run top to bottom for a missing or failed unit. Add --user on every systemctl and journalctl command when debugging rootless Quadlet.

Check Podman version first:

bash
podman --version

Reload after any source edit:

bash
sudo systemctl daemon-reload

Inspect whether systemd knows the unit:

bash
systemctl status web.service --no-pager

Trace back to the source file:

bash
systemctl show -p SourcePath web.service

Read the generated unit:

bash
systemctl cat web.service

Translate Quadlet in isolation:

bash
QUADLET_UNIT_DIRS=/tmp/quadlet-debug /usr/libexec/podman/quadlet -dryrun

Validate generated systemd syntax:

bash
systemd-analyze verify /run/systemd/generator/web.service

Read service logs:

bash
journalctl -u web.service -b --no-pager -n 20

Confirm whether Podman created a container:

bash
podman ps -a

Troubleshooting matrix

Symptom Likely layer First check
Unit ... not found Generator or path Search path, extension, daemon-reload, quadlet -dryrun
unsupported key in dry-run Generator / version podman --version, compare docs to installed Podman
Warning about unit changed on disk systemd cache daemon-reload before restart
active (exited) on .volume Oneshot resource unit Result=, journal exit status, podman volume ls
Service start timeout on .container / .kube systemd / pull or build Journal pull lines, raise TimeoutStartSec, pre-pull image
Wrong container name Quadlet source ContainerName= in .container
Works until logout User session loginctl show-user -p Linger

References


Summary

Quadlet failures split cleanly across layers. When systemctl reports unit not found, the generator never produced a service — check path, extension, reload, then QUADLET_UNIT_DIRS with quadlet -dryrun before opening Podman logs. Unsupported keys and version skew show up directly in generator output; systemd-analyze verify catches problems in the translated unit after reload.

Once a unit exists, SourcePath and systemctl cat tie the running service back to the editable source. Reload after every edit — systemd keeps the old ExecStart until you do. Resource Quadlets are oneshot services; check Result=, exit status, the journal, and the Podman resource instead of expecting a long-running active state.

Rootless boot and logout issues route to Rootless Podman Quadlet. Enable mechanics and [Install] depth stay in Podman Quadlet with systemd. This page absorbs the old unit-not-found slug — bookmark it whenever a Quadlet source is on disk but the matching .service never appears.


Frequently Asked Questions

1. Why does systemctl say Unit web.service not found for my Quadlet?

The generator never created web.service. Confirm the file is in a valid search path with a supported extension, run daemon-reload, then run the Quadlet generator in dry-run mode, optionally with QUADLET_UNIT_DIRS to isolate the source, before chasing Podman logs.

2. Do I need daemon-reload after every Quadlet edit?

Yes. systemd caches generated units. After you change a .container or other Quadlet source, run systemctl daemon-reload or systemctl --user daemon-reload before restart or enable, or systemd may keep the old ExecStart line.

3. Should I edit the file under /run/systemd/generator?

No. Generated .service files are recreated on every daemon-reload. Fix the Quadlet source under /etc/containers/systemd or ~/.config/containers/systemd, reload, then inspect again with systemctl cat.

4. What is the difference between generator dry-run and systemd-analyze verify?

Generator dry-run shows Quadlet translation errors such as unsupported keys. systemd-analyze verify checks the generated systemd unit syntax and dependencies after generators run. Use both when a unit fails to load or start.

5. Why is my volume Quadlet inactive dead even though it succeeded?

Resource Quadlets such as .volume, .network, .build, and .image generate Type=oneshot services, so they do not represent a continuously running process. Depending on the generated unit, you may see active (exited) or a completed/inactive state. Check Result=success, the command exit status, the journal, and whether the Podman resource exists before treating the state as a failure.
Deepak Prasad

R&D Engineer

Founder of GoLinuxCloud with more than 15 years of expertise in Linux, Python, Go, Laravel, DevOps, Kubernetes, Git, Shell scripting, OpenShift, AWS, Networking, and Security. With extensive experience, he excels across development, DevOps, networking, and security, delivering robust and efficient solutions for diverse projects.

  • Go (programming language)
  • Python (programming language)
  • DevOps
  • Computer Security
  • Cloud Computing
  • Kubernetes
  • Linux
  • Ansible (software)