From 7ecac4a65e0eb87a49d23db340e4619886024843 Mon Sep 17 00:00:00 2001 From: Jordan Rodgers Date: Thu, 12 Mar 2026 22:58:44 -0700 Subject: [PATCH] compat: return 409 Conflict when container name is already in use The Docker API spec defines HTTP 409 for POST /containers/create when the requested name is already in use. The handler was returning 500 for all errors from ContainerCreate, including ErrCtrExists. This mismatch breaks buildx parallel builds on Podman: buildx checks for a conflict response to safely converge multiple concurrent builders onto the already-running BuildKit container. With 500 it treats the conflict as a fatal error instead, causing all but the first parallel build to fail. The fix follows the same pattern already used in the rename handler, which correctly returns 409 for ErrCtrExists. The swagger annotation for this endpoint already documents the 409 response. Signed-off-by: Jordan Rodgers --- pkg/api/handlers/compat/containers_create.go | 4 ++++ .../python/rest_api/test_v2_0_0_container.py | 17 +++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/pkg/api/handlers/compat/containers_create.go b/pkg/api/handlers/compat/containers_create.go index a113b94ac2..68cc711839 100644 --- a/pkg/api/handlers/compat/containers_create.go +++ b/pkg/api/handlers/compat/containers_create.go @@ -127,6 +127,10 @@ func CreateContainer(w http.ResponseWriter, r *http.Request) { ic := abi.ContainerEngine{Libpod: runtime} report, err := ic.ContainerCreate(r.Context(), sg) if err != nil { + if errors.Is(err, define.ErrCtrExists) || errors.Is(err, storage.ErrDuplicateName) { + utils.Error(w, http.StatusConflict, fmt.Errorf("container create: %w", err)) + return + } utils.Error(w, http.StatusInternalServerError, fmt.Errorf("container create: %w", err)) return } diff --git a/test/apiv2/python/rest_api/test_v2_0_0_container.py b/test/apiv2/python/rest_api/test_v2_0_0_container.py index 3c3c00fb60..3c24298f4c 100644 --- a/test/apiv2/python/rest_api/test_v2_0_0_container.py +++ b/test/apiv2/python/rest_api/test_v2_0_0_container.py @@ -278,6 +278,23 @@ class ContainerTestCase(APITestCase): # is zero. I think the test needs some rewrite. # self.assertIsNotNone(prune_payload["ImagesDeleted"][1]["Deleted"]) + def test_create_duplicate_name(self): + name = f"Container_{random.getrandbits(160):x}" + payload = {"Cmd": ["top"], "Image": "alpine:latest"} + + r = requests.post( + self.podman_url + f"/v1.40/containers/create?name={name}", json=payload + ) + self.assertEqual(r.status_code, 201, r.text) + container_id = r.json()["Id"] + + r = requests.post( + self.podman_url + f"/v1.40/containers/create?name={name}", json=payload + ) + self.assertEqual(r.status_code, 409, r.text) + + requests.delete(self.podman_url + f"/v1.40/containers/{container_id}?force=true") + def test_status(self): r = requests.post( self.podman_url + "/v1.40/containers/create?name=topcontainer",