{"record":{"id":"b7d08f5d953e7864","repo":"slopus/happy","slug":"error-b7d08f","errorCode":null,"errorMessage":"error","messagePattern":"error","errorType":"http","errorClass":null,"httpStatus":500,"severity":"warning","filePath":"packages/happy-cli/src/claude/utils/startHookServer.ts","lineNumber":140,"sourceCode":"                    } catch (parseError) {\n                        logger.debug('[hookServer] Failed to parse hook data as JSON:', parseError);\n                    }\n\n                    // Support both snake_case (from Claude) and camelCase\n                    const sessionId = data.session_id || data.sessionId;\n                    if (sessionId) {\n                        logger.debug(`[hookServer] Session hook received session ID: ${sessionId}`);\n                        onSessionHook(sessionId, data);\n                    } else {\n                        logger.debug('[hookServer] Session hook received but no session_id found in data');\n                    }\n\n                    res.writeHead(200, { 'Content-Type': 'text/plain' }).end('ok');\n                } catch (error) {\n                    clearTimeout(timeout);\n                    logger.debug('[hookServer] Error handling session hook:', error);\n                    if (!res.headersSent) {\n                        res.writeHead(500).end('error');\n                    }\n                }\n                return;\n            }\n\n            // 404 for anything else\n            res.writeHead(404).end('not found');\n        });\n\n        // Listen on random available port\n        server.listen(0, '127.0.0.1', () => {\n            const address = server.address();\n            if (!address || typeof address === 'string') {\n                reject(new Error('Failed to get server address'));\n                return;\n            }\n\n            const port = address.port;","sourceCodeStart":122,"sourceCodeEnd":158,"githubUrl":"https://github.com/slopus/happy/blob/b824cd0a4681d41af631a8e422a813873e4455b0/packages/happy-cli/src/claude/utils/startHookServer.ts#L122-L158","documentation":"When handling the session-start hook throws (stdin parse error, handler exception), the server logs the error and responds 500 with body 'error' if headers haven't been sent. The logged 'error' corresponds to the caught exception surfaced in the handler's catch block.","triggerScenarios":"An exception inside the /hook/session-start handler — e.g. JSON.parse of malformed body, processing error, or stream read failure — triggers the catch path that writes the 500 'error' response.","commonSituations":"Hook client sends non-JSON or truncated payload; handler code throws on unexpected session data; request aborted mid-body causing read errors.","solutions":["Inspect debug logs ('Error handling session hook:') for the underlying exception","Validate that the hook client sends well-formed JSON and closes the stream cleanly","Retry the hook invocation after fixing the payload","Add explicit error normalization in the handler so failures produce actionable messages"],"exampleFix":"// before\nconst payload = JSON.parse(body.toString());\n// after\nlet payload;\ntry { payload = JSON.parse(body.toString()); } catch { payload = {}; }","handlingStrategy":"try-catch","validationCode":"const body = JSON.stringify(sessionData); // throws early if not serializable\nif (typeof sessionData !== 'object') throw new TypeError('session hook payload must be an object');","typeGuard":null,"tryCatchPattern":"try {\n  const res = await fetch(hookUrl, { method: 'POST', body: JSON.stringify(sessionData) });\n  if (res.status === 500) {\n    logger.error('Hook handler failed; check happy-cli debug logs for Error handling session hook');\n  }\n} catch (e) { /* network error */ }","preventionTips":["Send strictly JSON-serializable, well-formed payloads to the hook endpoint","Check CLI debug output for the wrapped underlying exception","Close the request stream cleanly to avoid partial-body parse errors","Validate session data shape before posting"],"tags":["http","hooks","error-handling"],"backgroundTag":"http-500-internal-error","analyzedSha":"b824cd0a4681d41af631a8e422a813873e4455b0","analyzedAt":"2026-08-31T23:12:36.205Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}