From c33812a430ad6a5f1fe83256434796f90838baff Mon Sep 17 00:00:00 2001 From: Rowan Smith Date: Thu, 26 Mar 2026 00:57:28 +1100 Subject: [PATCH] chore: switch agent gone response from 502 to 404 (#23090) When a user creates a workspace, opens the web terminal, then the workspace stops but the web terminal remains open the web terminal will retry the connection. Coder will issue a HTTP 502 Bad Gateway response when this occurs because coderd cannot connect to the workspace agent, however this is problematic as any load balancer sitting in front of Coder sees a 502 and thinks Coder is unhealthy. The main change is in https://github.com/coder/coder/pull/23090/changes#diff-bbe3b56ed3532289481a0e977867cd15048b7ca718ce676aae3f3332378eebc2R97, however the main test and downstream tests are also updated. This PR changes the response to a [HTTP 404](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/404) after internal discussion. image Created with the help of Mux, reviewed and tested by a human --- coderd/coderd_test.go | 4 ++-- coderd/workspaceapps/db_test.go | 2 +- coderd/workspaceapps/errors.go | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/coderd/coderd_test.go b/coderd/coderd_test.go index 0ff2a65e2d..0d0d32f553 100644 --- a/coderd/coderd_test.go +++ b/coderd/coderd_test.go @@ -384,9 +384,9 @@ func TestCSRFExempt(t *testing.T) { data, _ := io.ReadAll(resp.Body) _ = resp.Body.Close() - // A StatusBadGateway means Coderd tried to proxy to the agent and failed because the agent + // A StatusNotFound means Coderd tried to proxy to the agent and failed because the agent // was not there. This means CSRF did not block the app request, which is what we want. - require.Equal(t, http.StatusBadGateway, resp.StatusCode, "status code 500 is CSRF failure") + require.Equal(t, http.StatusNotFound, resp.StatusCode, "status code 500 is CSRF failure") require.NotContains(t, string(data), "CSRF") }) } diff --git a/coderd/workspaceapps/db_test.go b/coderd/workspaceapps/db_test.go index b856ff8882..5d5370661f 100644 --- a/coderd/workspaceapps/db_test.go +++ b/coderd/workspaceapps/db_test.go @@ -1016,7 +1016,7 @@ func Test_ResolveRequest(t *testing.T) { w := rw.Result() defer w.Body.Close() - require.Equal(t, http.StatusBadGateway, w.StatusCode) + require.Equal(t, http.StatusNotFound, w.StatusCode) assertConnLogContains(t, rw, r, connLogger, workspace, agentNameUnhealthy, appNameAgentUnhealthy, database.ConnectionTypeWorkspaceApp, me.ID) require.Len(t, connLogger.ConnectionLogs(), 1) diff --git a/coderd/workspaceapps/errors.go b/coderd/workspaceapps/errors.go index 22115db08d..a8d0c4eab3 100644 --- a/coderd/workspaceapps/errors.go +++ b/coderd/workspaceapps/errors.go @@ -77,7 +77,7 @@ func WriteWorkspaceApp500(log slog.Logger, accessURL *url.URL, rw http.ResponseW }) } -// WriteWorkspaceAppOffline writes a HTML 502 error page for a workspace app. If +// WriteWorkspaceAppOffline writes a HTML 404 error page for a workspace app. If // appReq is not nil, it will be used to log the request details at debug level. func WriteWorkspaceAppOffline(log slog.Logger, accessURL *url.URL, rw http.ResponseWriter, r *http.Request, appReq *Request, msg string) { if appReq != nil { @@ -94,7 +94,7 @@ func WriteWorkspaceAppOffline(log slog.Logger, accessURL *url.URL, rw http.Respo } site.RenderStaticErrorPage(rw, r, site.ErrorPageData{ - Status: http.StatusBadGateway, + Status: http.StatusNotFound, Title: "Application Unavailable", Description: msg, Actions: []site.Action{