{"record":{"id":"d264a2b969c2ed79","repo":"danny-avila/LibreChat","slug":"unexpected-response-from-server-status-respons","errorCode":null,"errorMessage":"Unexpected response from server; Status: ${response.status} ${response.statusText}","messagePattern":"Unexpected response from server; Status: (.+?) (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"client/src/hooks/SSE/useEventHandlers.ts","lineNumber":1092,"sourceCode":"        });\n\n        // Check if the response is JSON\n        const contentType = response.headers.get('content-type');\n        if (contentType != null && contentType.includes('application/json')) {\n          const data = await response.json();\n          if (response.status === 404) {\n            setIsSubmitting(false);\n            return;\n          }\n          if (data.final === true) {\n            finalHandler(data, submission);\n          } else {\n            cancelHandler(data, submission);\n          }\n        } else if (response.status === 204 || response.status === 200) {\n          setIsSubmitting(false);\n        } else {\n          throw new Error(\n            'Unexpected response from server; Status: ' +\n              response.status +\n              ' ' +\n              response.statusText,\n          );\n        }\n      } catch (error) {\n        const errorResponse = createErrorMessage({\n          getMessages,\n          submission,\n          error,\n        });\n        setMessages([...submission.messages, submission.userMessage, errorResponse]);\n        if (newConversation) {\n          newConversation({\n            template: { conversationId: conversationId || errorResponse.conversationId || v4() },\n            preset: tPresetSchema.parse(submission.conversation),\n          });","sourceCodeStart":1074,"sourceCodeEnd":1110,"githubUrl":"https://github.com/danny-avila/LibreChat/blob/5ff282f9006c436e561de1afd39a481bea1ef0d8/client/src/hooks/SSE/useEventHandlers.ts#L1074-L1110","documentation":"Thrown by the abort handler when the `POST {endpoint}/abort` request returns a response that is neither JSON nor a clean 200/204. The handler treats JSON responses via `finalHandler`/`cancelHandler` (and a JSON 404 as a silent stop), and 200/204 non-JSON as success; anything else (e.g. 401, 403, 500, or a non-JSON 404) falls through to this throw. The thrown error is caught immediately and surfaced in the chat as an error message — it is not re-thrown.","triggerScenarios":"The abort endpoint returns 401 because the user's JWT expired mid-conversation; 403 due to authorization changes; 500 from a server-side error during abort processing; the server returns an HTML error page (non-JSON) with a 404/500 status (e.g. a reverse-proxy 502/504 page); the endpoint route is misconfigured and returns a non-JSON body.","commonSituations":"Long-running chat where the JWT expires before the user hits stop; a reverse proxy (nginx) returning an HTML 502/504 when the upstream abort handler is down; the abort route returning the wrong content-type; deployment where the `/abort` route is missing and returns a non-JSON 404.","solutions":["Inspect the captured `response.status`/`statusText` — 401 means re-authenticate, 5xx/502/504 means the upstream is unhealthy, 404 non-JSON means the route is missing.","For 401, trigger a token refresh / re-login flow before retrying the abort.","For proxy HTML error pages, ensure the abort route is registered and returns JSON, and configure the proxy to pass through application responses.","Because the error is already caught and shown in-chat, no further handling is strictly required; the user can retry or re-authenticate."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Pre-check auth before aborting\nif (!token) throw new Error('Not authenticated');\n// Or: refresh token if it may be near expiry\nif (tokenExpired(token)) await refreshToken();","typeGuard":"function isJsonResponse(response: Response): boolean {\n  return (response.headers.get('content-type') ?? '').includes('application/json');\n}","tryCatchPattern":"try {\n  const response = await fetch(`${EndpointURLs[endpoint]}/abort`, { ... });\n  if (!response.ok && !isJsonResponse(response) && ![200, 204].includes(response.status)) {\n    throw new Error(`Unexpected response: ${response.status}`);\n  }\n} catch (err) {\n  createErrorMessage({ getMessages, submission, error: err }); // already surfaced in-chat\n}","preventionTips":["Refresh the JWT before it expires in long-running chats to avoid 401 abort failures.","Ensure the /abort route is registered and returns JSON, and that proxies pass application responses through.","Treat 5xx/proxy HTML errors as transient and let the user retry."],"tags":["sse","abort","network","http","chat","client"],"backgroundTag":null,"analyzedSha":"5ff282f9006c436e561de1afd39a481bea1ef0d8","analyzedAt":"2026-08-12T21:38:08.145Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}