{"record":{"id":"dc8e54b8cae5c18f","repo":"SigNoz/signoz","slug":"err-error","errorCode":null,"errorMessage":"err.Error()","messagePattern":"err\\.Error\\(\\)","errorType":"http","errorClass":null,"httpStatus":500,"severity":"warning","filePath":"pkg/http/render/render.go","lineNumber":122,"sourceCode":"\t\thttpCode = http.StatusNotImplemented\n\tcase errors.TypeForbidden:\n\t\thttpCode = http.StatusForbidden\n\tcase errors.TypeCanceled:\n\t\thttpCode = statusClientClosedConnection\n\tcase errors.TypeTimeout:\n\t\thttpCode = http.StatusGatewayTimeout\n\tcase errors.TypeFatal:\n\t\thttpCode = http.StatusInternalServerError\n\tcase errors.TypeLicenseUnavailable:\n\t\thttpCode = http.StatusUnavailableForLegalReasons\n\tcase errors.TypeTooManyRequests:\n\t\thttpCode = http.StatusTooManyRequests\n\t}\n\n\tbody, err := json.Marshal(&ErrorResponse{Status: StatusError.s, Error: errors.AsJSON(cause)})\n\tif err != nil {\n\t\t// this should never be the case\n\t\thttp.Error(rw, err.Error(), http.StatusInternalServerError)\n\t\treturn\n\t}\n\n\t// Retry-After carries the explicit delay declared via\n\t// errors.WithRetryAfter. Set it before WriteHeader so headers go on the wire.\n\td := errors.RetryDelayOf(cause)\n\tif d.Seconds() > 0 {\n\t\trw.Header().Set(\"Retry-After\", strconv.Itoa(int(math.Ceil(d.Seconds()))))\n\t}\n\n\trw.Header().Set(\"Content-Type\", \"application/json\")\n\trw.WriteHeader(httpCode)\n\t_, _ = rw.Write(body)\n}\n","sourceCodeStart":104,"sourceCodeEnd":137,"githubUrl":"https://github.com/SigNoz/signoz/blob/5069bf80b08f1f00d7e014eccc09902f9871004f/pkg/http/render/render.go#L104-L137","documentation":"In render.Error, after mapping the error to an HTTP status (including 429 with Retry-After), the ErrorResponse body is json.Marshal'd. If that marshal fails (noted in-source as 'this should never be the case'), the handler falls back to http.Error with the marshal error and a raw 500.","triggerScenarios":"Essentially unreachable in practice: it requires ErrorResponse containing errors.AsJSON(cause) to be unmarshalable — e.g. a cause whose JSON encoding panics on unsupported types — while the original status/code information is lost.","commonSituations":"None realistic; if observed, it indicates a programming bug where the error cause carries non-serializable data (channels, cycles) rather than a user mistake.","solutions":["Log the original cause before rendering so context is not lost if this path triggers","Ensure custom error types only carry serializable fields","Report as a bug if reproducible — this branch is documented as unreachable"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"if _, err := json.Marshal(body); err != nil {\n    http.Error(rw, \"internal error\", 500) // generic, log details server-side\n}","preventionTips":["Keep error cause types serializable","Log the original error before rendering"],"tags":["http","render","internal","marshal"],"backgroundTag":"http-error-rendering-failed","analyzedSha":"5069bf80b08f1f00d7e014eccc09902f9871004f","analyzedAt":"2026-08-28T06:22:12.824Z","schemaVersion":2},"datasetVersion":"2026-08-28T11:17:15.048Z"}