#13266·portainer

When deleting a Kubernetes Deployment from UI, the Portainer stack object is not removed

Author: mlinopsCreated Aug 18, 2026Updated Sep 17, 2026
Labelskind/bugbug/need-confirmationbot/triage-completerelease/3.0.0

Before you start please confirm the following.

  • Yes, I've searched similar issues on GitHub.
  • Yes, I've checked whether this issue is covered in the Portainer documentation.

Problem Description

On Portainer 2.39.3 LTS, removing a Kubernetes Deployment from Applications (UI) does not remove the Portainer stack object.

This Kubernetes environment has no Stacks list in the UI (unlike Docker). Cleanup is only Applications and Namespaces.

After Remove:

  • Applications list is empty for that name.
  • GET /api/kubernetes/{endpointId}/applications returns [].
  • GET /api/stacks still returns the stack with "Status": 1.
  • Creating or updating a stack with the same name then hits a stale record (name in use, or update of an empty stack).

How the stack was created does not matter (Git, string, UI form, API). Deleting live objects in the UI — Deployment, Service, Namespace — in any order still leaves the Portainer stack record.

This is confirmed in the 2.39.3 source (links below). Applications → Remove never calls DELETE /api/stacks/{id}. It deletes the Deployment via the Kubernetes API, then DELETE /api/stacks/name/{name}?namespace={live ResourcePool}. If stack.Namespace in the DB does not equal that query (including "Namespace": ""), the handler skips the row and still returns 204. Namespaces → Remove deletes cluster objects and also does not delete the stack record (#5897, still true on 2.39.3).

Expected Behavior

  1. Removing live Kubernetes objects in Applications / Namespaces should also remove the Portainer stack record, or fail visibly if it cannot.
  2. Applications → Remove should undeploy the stored manifest (KubernetesDeployer.Remove) and delete the DB row — same as DELETE /api/stacks/{id}?endpointId=.
  3. If stack.Namespace is empty, delete-by-name should match on name + endpointId, not require an exact namespace string.
  4. If delete-by-name matched zero stacks, return 404, not 204.

Actual Behavior

1. Applications → Remove deletes the Deployment, not the Portainer stack

ApplicationsDatatable.tsx @ 2.39.3 and useDeleteApplicationsMutation.ts @ 2.39.3

typescript
await axios.delete(
  `/endpoints/${environmentId}/kubernetes/apis/apps/v1/namespaces/${application.ResourcePool}/deployments/${application.Name}`
);

Then, if the in-memory application list for that name is empty:

typescript
await axios.delete(`/stacks/name/${stack.Name}`, {
  params: {
    external: false,
    endpointId: environmentId,
    namespace: stack.ResourcePool, // live k8s NS, not stack.Namespace from the DB
  },
});

There is no DELETE /api/stacks/{id}. kind: Namespace and other non-application objects from the manifest are not deleted this way (#5715).

2. API skips a stack whose Namespace does not equal the query, then returns 204

stack_delete.go stackDeleteKubernetesByName @ 2.39.3

go
if stack.Namespace != namespace {
    continue
}

If stack.Namespace == "" and the query is namespace=demo-ns, stacksToDelete is empty. There is no 404:

go
if len(errors) > 0 {
    return httperror.InternalServerError(...)
}
return response.Empty(w) // 204 even when nothing was deleted

The UI then shows success. GET /api/stacks/{id} still has "Status": 1, "Namespace": "".

The working path in the same file is stackDelete (DELETE /api/stacks/{id}?endpointId=): it does not compare namespace, runs KubernetesDeployer.Remove, then Stack().Delete.

Steps to Reproduce

  1. Kubernetes environment on Portainer 2.39.3 LTS.
  2. Create a Kubernetes stack any way (Git, string YAML, UI “deploy from manifest”, API). Note Id / Name from GET /api/stacks.
  3. In the UI, delete live resources in any order, for example:
    • Applications → Remove the Deployment
    • Namespaces → Remove the namespace
  4. UI reports success. Workloads in the cluster are gone (or the namespace is gone).
  5. GET /api/stacks/{id} — Portainer stack object is still there (Status: 1). Metadata is not removed.

Portainer logs or screenshots

API after UI Remove (redacted):

json
{
  "Id": 4382,
  "Name": "example-stack",
  "Type": 3,
  "EndpointId": 1,
  "Status": 1,
  "Namespace": "",
  "EntryPoint": "path/to/manifest.yaml"
}
GET /api/kubernetes/{endpointId}/applications → []

Portainer version

2.39.3

Portainer Edition

Community Edition (CE)

Platform and Version

Kubectl v1.35.1

OS and Architecture

Oracle Linux Server 9.8, x86_64

Browser

No response

What command did you use to deploy Portainer?

bash

Additional Information

The UI in 2.44.0 is still: Applications → Remove hits k8s Deployment, then DELETE /stacks/name/…?namespace=ResourcePool, not DELETE /api/stacks/{id}. Based on the code.