diff --git a/internal/api/handlers_snapshots.go b/internal/api/handlers_snapshots.go index 8667edb..f48539a 100644 --- a/internal/api/handlers_snapshots.go +++ b/internal/api/handlers_snapshots.go @@ -93,8 +93,15 @@ func (h *snapshotHandler) Create(w http.ResponseWriter, r *http.Request) { writeError(w, http.StatusConflict, "already_exists", "snapshot name already exists; use ?overwrite=true to replace") return } + // Delete old files from the agent before removing the DB record. + if _, err := h.agent.DeleteSnapshot(ctx, connect.NewRequest(&pb.DeleteSnapshotRequest{Name: req.Name})); err != nil { + status, code, msg := agentErrToHTTP(err) + writeError(w, status, code, "failed to delete existing snapshot files: "+msg) + return + } if err := h.db.DeleteTemplateByTeam(ctx, db.DeleteTemplateByTeamParams{Name: req.Name, TeamID: ac.TeamID}); err != nil { - slog.Warn("failed to delete existing template", "name", req.Name, "error", err) + writeError(w, http.StatusInternalServerError, "db_error", "failed to remove existing template record") + return } } @@ -182,7 +189,9 @@ func (h *snapshotHandler) Delete(w http.ResponseWriter, r *http.Request) { if _, err := h.agent.DeleteSnapshot(ctx, connect.NewRequest(&pb.DeleteSnapshotRequest{ Name: name, })); err != nil { - slog.Warn("delete snapshot: agent RPC failed", "name", name, "error", err) + status, code, msg := agentErrToHTTP(err) + writeError(w, status, code, "failed to delete snapshot files: "+msg) + return } if err := h.db.DeleteTemplateByTeam(ctx, db.DeleteTemplateByTeamParams{Name: name, TeamID: ac.TeamID}); err != nil { diff --git a/internal/service/sandbox.go b/internal/service/sandbox.go index 83a645d..ae4bac3 100644 --- a/internal/service/sandbox.go +++ b/internal/service/sandbox.go @@ -181,11 +181,11 @@ func (s *SandboxService) Destroy(ctx context.Context, sandboxID, teamID string) return fmt.Errorf("sandbox not found: %w", err) } - // Best-effort destroy on host agent — sandbox may already be gone. + // Destroy on host agent. A not-found response is fine — sandbox is already gone. if _, err := s.Agent.DestroySandbox(ctx, connect.NewRequest(&pb.DestroySandboxRequest{ SandboxId: sandboxID, - })); err != nil { - slog.Warn("destroy: agent RPC failed (sandbox may already be gone)", "sandbox_id", sandboxID, "error", err) + })); err != nil && connect.CodeOf(err) != connect.CodeNotFound { + return fmt.Errorf("agent destroy: %w", err) } if _, err := s.DB.UpdateSandboxStatus(ctx, db.UpdateSandboxStatusParams{