{"record":{"id":"78a2a6432f61facd","repo":"github/github-mcp-server","slug":"internal-error","errorCode":null,"errorMessage":"internal error","messagePattern":"internal error","errorType":"http","errorClass":null,"httpStatus":500,"severity":"warning","filePath":"internal/oauth/callback.go","lineNumber":146,"sourceCode":"\tselect {\n\tcase res := <-cs.results:\n\t\treturn res.code, res.err\n\tcase <-ctx.Done():\n\t\treturn \"\", ctx.Err()\n\t}\n}\n\nfunc (cs *callbackServer) close() {\n\tshutdownCtx, cancel := context.WithTimeout(context.Background(), 2*time.Second)\n\tdefer cancel()\n\t_ = cs.server.Shutdown(shutdownCtx)\n\t_ = cs.listener.Close()\n}\n\nfunc renderSuccess(w http.ResponseWriter) {\n\tw.Header().Set(\"Content-Type\", \"text/html; charset=utf-8\")\n\tif err := successTemplate.Execute(w, nil); err != nil {\n\t\thttp.Error(w, \"internal error\", http.StatusInternalServerError)\n\t}\n}\n\n// renderError shows the failure page. html/template auto-escapes msg, so a\n// hostile error_description cannot inject markup.\nfunc renderError(w http.ResponseWriter, msg string) {\n\tw.Header().Set(\"Content-Type\", \"text/html; charset=utf-8\")\n\tif err := errorTemplate.Execute(w, struct{ ErrorMessage string }{ErrorMessage: msg}); err != nil {\n\t\thttp.Error(w, \"internal error\", http.StatusInternalServerError)\n\t}\n}\n","sourceCodeStart":128,"sourceCodeEnd":158,"githubUrl":"https://github.com/github/github-mcp-server/blob/0ea1f775a7c73eff1bd2e25904d01136756bbfe2/internal/oauth/callback.go#L128-L158","documentation":"While rendering the OAuth callback success page, successTemplate.Execute returned an error and the handler responds with a bare 500 'internal error' as a last resort. The template is static, pre-parsed, and executed with nil data, so in practice Execute fails because the client disconnected mid-write (broken pipe) - at that point the token exchange has already succeeded. Persistent occurrences would indicate corrupted embedded templates.","triggerScenarios":"User closes the browser tab or the connection drops exactly as the success page streams out at the end of the OAuth flow.","commonSituations":"End users canceling at the final redirect; mobile browsers backgrounding during callback; scanners hitting the callback URL and disconnecting.","solutions":["Treat one-off occurrences as benign - the authorization already completed before rendering","If persistent, rebuild the binary to rule out corrupted embedded templates","Ensure no middleware writes headers before the callback handler runs"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err := successTemplate.Execute(w, nil); err != nil {\n\t// headers may already be flushed; the 500 fallback is best-effort - log at warn, not error\n\thttp.Error(w, \"internal error\", http.StatusInternalServerError)\n}","preventionTips":["Log template execution failures at warn level - client aborts during OAuth callbacks are routine","Keep callback responses small so the mid-write abort window is tiny","Test the callback handler against a client that disconnects mid-read"],"tags":["go","oauth","html-template","http","client-disconnect"],"backgroundTag":null,"analyzedSha":"0ea1f775a7c73eff1bd2e25904d01136756bbfe2","analyzedAt":"2026-08-15T18:10:19.804Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}