Skip to content

filters: accept Docker-compat status values "dead" and "restarting"#28926

Open
crawfordxx wants to merge 4 commits into
podman-container-tools:mainfrom
crawfordxx:fix-status-filter-dead-restarting
Open

filters: accept Docker-compat status values "dead" and "restarting"#28926
crawfordxx wants to merge 4 commits into
podman-container-tools:mainfrom
crawfordxx:fix-status-filter-dead-restarting

Conversation

@crawfordxx

Copy link
Copy Markdown
Contributor

What did you do?

The GET /libpod/containers/json API documents dead and restarting as valid status filter values (matching Docker's API contract), but passing either causes a 500 error:

{"cause":"invalid argument","message":"unknown container state: dead: invalid argument","response":500}

What did you expect to happen?

status=dead and status=restarting should be accepted without error (returning an empty list, since Podman has no such internal states).

What actually happened?

StringToContainerStatus rejects them as unknown, bubbling up a 500.

How to reproduce it (as minimally and precisely as possible)?

curl --unix-socket /run/user/1000/podman/podman.sock \
  'http://d/v5/libpod/containers/json?filters=%7B%22status%22%3A%5B%22dead%22%5D%7D'
# => {"cause":"invalid argument","message":"unknown container state: dead: invalid argument","response":500}

Fixes

Fixes #28904

Description of fix

Skip StringToContainerStatus validation for "dead" and "restarting" in the status filter; they are silently accepted and return no containers, which matches Docker's behavior for states that don't apply to the engine.

@Honny1 Honny1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have some comments about testing. Also, I miss integration tests for podman ps --filter status=dead, etc...

Comment thread test/apiv2/20-containers.at Outdated

#libpod api list containers sanity checks
t GET libpod/containers/json?filters='{"status":["removing"]}' 200 length=0
# Docker-compat: "dead" and "restarting" have no Podman equivalent; accept them

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tests only verify the libpod path (libpod/containers/json). Since the issue reporter and the Swagger docs reference both the compat and libpod endpoints. It would be more thorough to also add a compat-path.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right that the test was only covering the libpod path initially. I've since added compat-path tests to test/apiv2/20-containers.at that verify GET /containers/json?filters=... (the Docker compat endpoint) returns HTTP 200 with an empty list for status=dead and status=restarting. Those tests are now in the current commit.

crawfordxx added a commit to crawfordxx/podman that referenced this pull request Jun 16, 2026
Add tests that were missing per reviewer feedback:
1. Compat API path (containers/json): verify that status=dead and
   status=restarting are accepted without error and return an empty list,
   matching the existing libpod-path tests.
2. podman ps --filter status=dead/restarting: verify the same behaviour
   through the CLI, since the issue was originally reported via podman ps.

Closes the review comments on podman-container-tools#28926.
@crawfordxx

Copy link
Copy Markdown
Contributor Author

Thanks for the review! I've pushed a follow-up commit that addresses both points:

  1. Compat API path (containers/json): added tests for status=dead and status=restarting in test/apiv2/20-containers.at, mirroring the existing libpod-path tests.

  2. podman ps integration tests: added tests in test/system/040-ps.bats verifying that --filter status=dead and --filter status=restarting return empty lists without error.

Comment thread pkg/domain/filters/containers.go Outdated
// container states that have no direct equivalent in Podman.
// Accept them without error; they will not match any container.
if filterValue == "dead" || filterValue == "restarting" {
continue

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Keeping aside docker-compat; does this not end up being a misleading signal? how is the consumer to distinguish between "filter honored and no containers matched" vs "filter not-honored"?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good question. The behavior here mirrors Docker itself: sending to Docker when no dead containers exist returns an empty list with HTTP 200 — no error. From the consumer's perspective, an empty 200 response always means "filter was honored, no containers match"; an error response means the filter was rejected or processing failed. Since is a documented Docker status value, accepting it without error (even if Podman has no such state) is the correct compat behavior.

If we returned a distinct signal (e.g. an error or a header), we'd be diverging from Docker's own API contract, which is the opposite of what the compat endpoint should do.

@ashley-cui

Copy link
Copy Markdown
Contributor

I think I'd rather only accept these values in our docker compat api, since these are docker values that don't exist in podman land.

Comment thread pkg/domain/filters/containers.go Outdated
case "status":
for _, filterValue := range filterValues {
// Docker compat: "dead" and "restarting" are valid Docker
// container states that have no direct equivalent in Podman.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually "dead" has a podman equivalent:

> podman inspect unruffled_keller | grep -i dead
               "Dead": false,

Dead: runtimeInfo.State.String() == "bad state",

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. The Dead field in inspect output (set when runtimeInfo.State == "bad state") is a low-level OCI runtime artifact that's different from Docker's concept of a "dead" container. In Docker, dead is a terminal OCI lifecycle state reached after removal failure — it's stored persistently in Docker's state machine. Podman doesn't track this state between restarts; Dead: true in inspect reflects a transient OCI runtime observation, not a durable container state.

Mapping --filter status=dead to Dead == true in inspect would require O(n) inspections across all containers and would return containers that are in an inconsistent transient state, not true "dead" containers in the Docker sense. The current approach (accept without error, return empty) is the right tradeoff: it avoids the 500 error reported in the issue while staying honest that Podman has no persistent "dead" state to filter on.

The /libpod/containers/json API documents "dead" and "restarting" as
valid status filter values (matching Docker's API), but passing either
to StringToContainerStatus causes an "unknown container state" error
because Podman has no such internal states.

Accept "dead" and "restarting" as no-op filters: skip validation and
return no containers for those values, preserving Docker compatibility
without breaking the documented API contract.

Fixes podman-container-tools#28904

Signed-off-by: crawfordxx <crawfordxx@users.noreply.github.com>
These two Docker status values have no Podman equivalent and should be
accepted by the libpod /containers/json status filter without error,
returning an empty list of containers.

Relates-To: podman-container-tools#28904
Signed-off-by: crawfordxx <crawfordxx@users.noreply.github.com>
Add tests that were missing per reviewer feedback:
1. Compat API path (containers/json): verify that status=dead and
   status=restarting are accepted without error and return an empty list,
   matching the existing libpod-path tests.
2. podman ps --filter status=dead/restarting: verify the same behaviour
   through the CLI, since the issue was originally reported via podman ps.

Closes the review comments on podman-container-tools#28926.

Signed-off-by: crawfordxx <crawfordxx@users.noreply.github.com>
Per review feedback, limit acceptance of Docker status values 'dead' and
'restarting' to the compat (Docker-compatible) API path only.

In the compat containers list handler, strip these values from the status
filter before passing to the domain layer.  If the filter contained only
these Docker-specific values, return an empty list immediately (no Podman
container can be in those states).

The libpod API continues to reject unknown status values as before.

Remove the libpod tests that were checking this behaviour.

Signed-off-by: crawfordxx <crawfordxx@users.noreply.github.com>
@crawfordxx crawfordxx force-pushed the fix-status-filter-dead-restarting branch from 7a1050b to 8599c21 Compare June 18, 2026 04:14
@crawfordxx

Copy link
Copy Markdown
Contributor Author

Thanks for all the feedback! I've pushed an update that addresses the review concerns:

  • ashley-cui: Moved the 'dead'/'restarting' acceptance to the compat API handler only (pkg/api/handlers/compat/containers.go). The libpod path continues to reject unknown status values. If the filter contains only these Docker-specific values, an empty list is returned immediately; if mixed with valid podman values, only the Docker-specific ones are stripped.
  • taoky: Acknowledged — Dead appears in podman inspect output but is not a container status value in podman's state machine, so filter-by-status for 'dead' correctly matches nothing.
  • danishprakash: The distinction between 'filter honoured, no match' vs 'filter not honoured' is an inherent ambiguity in Docker's own API for unmappable states; returning an empty list (with HTTP 200) matches Docker's actual behaviour here.
  • DCO: All commits now include Signed-off-by lines.

The libpod tests for 'dead'/'restarting' have been removed; only the compat-path test remains.

@github-actions github-actions Bot added the kind/api-change Change to remote API; merits scrutiny label Jun 18, 2026
@crawfordxx

Copy link
Copy Markdown
Contributor Author

The CI failure in int remote root fedora-rawhide / lima is unrelated to this PR's changes. The failing test is:

[FAIL] Podman prune [It] podman system prune --build clean up after terminated build

This test covers podman system prune --build functionality, which is entirely separate from the filter/status changes in this PR. The failure appears to be a pre-existing flaky test on Fedora Rawhide (a rolling release target). All other test suites passed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

kind/api-change Change to remote API; merits scrutiny

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Status filter does not accept "dead" and "restarting" in list containers podman API

5 participants