{"record":{"id":"94574bc5696e2226","repo":"projectdiscovery/katana","slug":"err-error","errorCode":null,"errorMessage":"err.Error()","messagePattern":"err\\.Error\\(\\)","errorType":"http","errorClass":null,"httpStatus":500,"severity":"warning","filePath":"pkg/engine/headless/debugger.go","lineNumber":108,"sourceCode":"\tnow := time.Now()\n\tfor _, au := range cd.activeURLs {\n\t\tcopy := *au\n\t\tcopy.Duration = now.Sub(au.StartTime).String()\n\t\turls = append(urls, copy)\n\t}\n\treturn urls\n}\n\n// HTTP handlers\nfunc (cd *CrawlDebugger) handleActiveURLs(w http.ResponseWriter, r *http.Request) {\n\tw.Header().Set(\"Content-Type\", \"application/json\")\n\tactive := cd.GetActiveURLs()\n\tif err := json.NewEncoder(w).Encode(map[string]interface{}{\n\t\t\"timestamp\":   time.Now().Format(time.RFC3339),\n\t\t\"active_urls\": active,\n\t\t\"count\":       len(active),\n\t}); err != nil {\n\t\thttp.Error(w, err.Error(), http.StatusInternalServerError)\n\t}\n}\n\nfunc (cd *CrawlDebugger) handleHealth(w http.ResponseWriter, r *http.Request) {\n\tw.Header().Set(\"Content-Type\", \"application/json\")\n\tif err := json.NewEncoder(w).Encode(map[string]interface{}{\n\t\t\"status\":    \"ok\",\n\t\t\"timestamp\": time.Now().Format(time.RFC3339),\n\t}); err != nil {\n\t\thttp.Error(w, err.Error(), http.StatusInternalServerError)\n\t}\n}\n\nfunc (cd *CrawlDebugger) Close() {\n\tif cd == nil {\n\t\treturn\n\t}\n","sourceCodeStart":90,"sourceCodeEnd":126,"githubUrl":"https://github.com/projectdiscovery/katana/blob/e3e742739c3746f085943ce918fb4e2b8daf6fe6/pkg/engine/headless/debugger.go#L90-L126","documentation":"In the crawl debugger's HTTP handler handleActiveURLs, any failure encoding the active-URLs JSON is written back as an HTTP 500 with err.Error(). This is a JSON marshaling/encoding failure at response time — the payload (timestamps, active URL list) could not be serialized. In practice rare, since the payload contains only strings and ints.","triggerScenarios":"json.NewEncoder(w).Encode fails, e.g. because the ResponseWriter breaks mid-write (client disconnected), or the payload contains unsupported values from GetActiveURLs.","commonSituations":"Client closed the debugger connection while the handler was writing; custom types returned by GetActiveURLs that are not JSON-marshalable after code changes.","solutions":["Check the client connection; disconnecting browsers cause broken-pipe errors that surface here.","Verify GetActiveURLs returns only JSON-serializable types (strings/slices).","Log the error server-side as well, since writing it to a broken connection loses the diagnostic.","Consider http.StatusClientClosedRequest handling for write errors after headers are sent."],"exampleFix":"// before\nif err := json.NewEncoder(w).Encode(payload); err != nil {\n    http.Error(w, err.Error(), http.StatusInternalServerError)\n}\n// after\nif err := json.NewEncoder(w).Encode(payload); err != nil {\n    log.Printf(\"debugger: encode active_urls: %v\", err) // http.Error may also fail if headers already sent\n    return\n}","handlingStrategy":"try-catch","validationCode":"// sanity-check payload marshalability before writing\nif _, err := json.Marshal(cd.GetActiveURLs()); err != nil {\n    log.Printf(\"active_urls not marshalable: %v\", err)\n}","typeGuard":null,"tryCatchPattern":"// Go: log encode errors instead of a 500 that also fails\nif err := json.NewEncoder(w).Encode(payload); err != nil {\n    log.Printf(\"debugger active_urls encode: %v\", err)\n}","preventionTips":["Keep GetActiveURLs return types strictly JSON-serializable.","Expect client disconnects on long-lived debugger endpoints; log rather than 500.","Test debugger handlers with a client that closes the connection early."],"tags":["http","json","debugger"],"backgroundTag":"json-encode-failed","analyzedSha":"e3e742739c3746f085943ce918fb4e2b8daf6fe6","analyzedAt":"2026-09-03T14:55:13.248Z","contentChangedAt":"2026-09-03T14:55:13.248Z","schemaVersion":2},"datasetVersion":"2026-09-10T17:17:09.494Z"}