{"record":{"id":"4be772fe408be07a","repo":"wavetermdev/waveterm","slug":"recerr-error","errorCode":null,"errorMessage":"recErr.Error()","messagePattern":"recErr\\.Error\\(\\)","errorType":"http","errorClass":null,"httpStatus":500,"severity":"critical","filePath":"pkg/web/web.go","lineNumber":397,"sourceCode":"\tActive bool `json:\"active\"`\n\tOpen   bool `json:\"open\"`\n}\n\nfunc WebFnWrap(opts WebFnOpts, fn WebFnType) WebFnType {\n\treturn func(w http.ResponseWriter, r *http.Request) {\n\t\tdefer func() {\n\t\t\trecErr := panichandler.PanicHandler(\"WebFnWrap\", recover())\n\t\t\tif recErr == nil {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif opts.JsonErrors {\n\t\t\t\tjsonRtn := marshalReturnValue(nil, recErr)\n\t\t\t\tw.Header().Set(ContentTypeHeaderKey, ContentTypeJson)\n\t\t\t\tw.Header().Set(ContentLengthHeaderKey, fmt.Sprintf(\"%d\", len(jsonRtn)))\n\t\t\t\tw.WriteHeader(http.StatusOK)\n\t\t\t\tw.Write(jsonRtn)\n\t\t\t} else {\n\t\t\t\thttp.Error(w, recErr.Error(), http.StatusInternalServerError)\n\t\t\t}\n\t\t}()\n\t\tif !opts.AllowCaching {\n\t\t\tw.Header().Set(CacheControlHeaderKey, CacheControlHeaderNoCache)\n\t\t}\n\t\tw.Header().Set(\"Access-Control-Expose-Headers\", \"X-ZoneFileInfo\")\n\n\t\t// Handle CORS preflight OPTIONS requests without auth validation\n\t\tif r.Method == http.MethodOptions {\n\t\t\tw.WriteHeader(http.StatusOK)\n\t\t\treturn\n\t\t}\n\n\t\terr := authkey.ValidateIncomingRequest(r)\n\t\tif err != nil {\n\t\t\tw.WriteHeader(http.StatusUnauthorized)\n\t\t\tw.Write([]byte(fmt.Sprintf(\"error validating authkey: %v\", err)))\n\t\t\treturn","sourceCodeStart":379,"sourceCodeEnd":415,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/web/web.go#L379-L415","documentation":"This is the plain-text 500 response emitted by WebFnWrap (pkg/web/web.go:397) when a wrapped HTTP handler panics and the route was registered without JsonErrors. PanicHandler recovers the panic and converts it to an error; http.Error then writes recErr.Error() with HTTP 500. It signals an unexpected bug inside the handler, not a client mistake.","triggerScenarios":"Any handler wrapped with WebFnWrap panics (nil dereference, index out of range, failed type assertion) while opts.JsonErrors is false. The panic string becomes the response body with status 500.","commonSituations":"Developers hit this when a query parameter is missing and the handler indexes into an empty slice, when a JSON field is absent and a cast like r.URL.Query().Get(...) is used unchecked downstream, or after a refactor introduced a nil map/slice access in a web endpoint.","solutions":["Read the panic message in the 500 response body and the server log entry from PanicHandler to locate the panicking handler and stack trace.","Fix the underlying nil/ out-of-range bug in the wrapped handler function.","Add defensive checks (nil maps, len() guards, ok-style type assertions) in the handler before dereferencing.","If the client should receive structured JSON errors, register the route with WebFnOpts{JsonErrors: true} so panics are marshaled via marshalReturnValue instead of plain text.","Reproduce locally with a request matching the handler's expected parameters and confirm the 500 no longer occurs."],"exampleFix":"// before: unchecked slice access in a WebFnWrap'd handler\nparts := strings.Split(r.URL.Path, \"/\")\nuse(parts[2]) // panics on short paths\n\n// after\nif len(parts) < 3 {\n    http.Error(w, \"path is required\", http.StatusBadRequest)\n    return\n}\nuse(parts[2])","handlingStrategy":"try-catch","validationCode":"// client-side pre-check: nothing prevents a server panic, but validate inputs before calling\nif (!params.path || params.path.length === 0) throw new Error(\"path is required\");","typeGuard":null,"tryCatchPattern":"const resp = await fetch(url, opts);\nif (resp.status === 500) {\n  const msg = await resp.text();\n  throw new Error(`handler panic: ${msg}`);\n}\n// JSON-errors routes: parse {isError, error} from the 200 body\nconst body = await resp.json();\nif (body.isError) throw new Error(body.error);","preventionTips":["Wrap risky handler logic with nil/length checks before dereferencing request data.","Register web routes with JsonErrors: true so panics come back as structured JSON.","Watch server logs for PanicHandler stack traces and fix them immediately.","Cover handlers with tests that send missing/short query parameters."],"tags":["go","http","panic","internal-server-error"],"backgroundTag":"http-handler-panic","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}