From ae2cea3410ea4f8f57aeb38ad5b2b5b4c320efe1 Mon Sep 17 00:00:00 2001 From: "A. F. Dudley" Date: Wed, 18 Mar 2026 18:47:05 +0000 Subject: [PATCH] fix: never delete namespace on deployment down down() deleted the entire namespace when it wasn't explicitly set in the spec. This causes a race condition on restart: up() tries to create resources in a namespace that's still terminating, getting 403 Forbidden. Always use _delete_resources_by_label() instead. The namespace is cheap to keep and required for immediate up() after down(). This also matches the shared-namespace behavior, making down() consistent regardless of namespace configuration. Co-Authored-By: Claude Opus 4.6 (1M context) --- stack_orchestrator/deploy/k8s/deploy_k8s.py | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/stack_orchestrator/deploy/k8s/deploy_k8s.py b/stack_orchestrator/deploy/k8s/deploy_k8s.py index e9ddc5e9..db359476 100644 --- a/stack_orchestrator/deploy/k8s/deploy_k8s.py +++ b/stack_orchestrator/deploy/k8s/deploy_k8s.py @@ -581,14 +581,11 @@ class K8sDeployer(Deployer): if opts.o.debug: print(f"Error listing PVs: {e}") - # When namespace is explicitly set in the spec, it may be shared with - # other stacks — delete only this stack's resources by label. - # Otherwise the namespace is owned by this deployment, delete it entirely. - shared_namespace = self.deployment_context.spec.get_namespace() is not None - if shared_namespace: - self._delete_resources_by_label(app_label, volumes) - else: - self._delete_namespace() + # Always delete resources by label, never delete the namespace itself. + # Namespace deletion causes a race condition on restart: up() tries to + # create resources in a namespace that's still terminating (403 Forbidden). + # The namespace is cheap to keep and required for immediate up() after down(). + self._delete_resources_by_label(app_label, volumes) if self.is_kind() and not self.skip_cluster_management: # Destroy the kind cluster