{"record":{"id":"71149b599fd75f74","repo":"n8n-io/n8n","slug":"500-71149b","errorCode":"500","errorMessage":"e.message","messagePattern":"e\\.message","errorType":"http","errorClass":null,"httpStatus":500,"severity":"error","filePath":"packages/cli/src/controllers/ai.controller.ts","lineNumber":136,"sourceCode":"\t\t\t\t\t\t\trole: 'assistant',\n\t\t\t\t\t\t\ttype: 'error',\n\t\t\t\t\t\t\tcontent: streamError.message,\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t};\n\t\t\t\tres.write(JSON.stringify(errorChunk) + STREAM_SEPARATOR);\n\t\t\t} finally {\n\t\t\t\t// Clean up event listener\n\t\t\t\tres.off('close', handleClose);\n\t\t\t}\n\n\t\t\tres.end();\n\t\t} catch (e) {\n\t\t\t// This catch block handles errors that occur before streaming starts\n\t\t\t// Since headers haven't been sent yet, we can still send a proper error response\n\t\t\tassert(e instanceof Error);\n\t\t\tif (!res.headersSent) {\n\t\t\t\tres.status(500).json({\n\t\t\t\t\tcode: 500,\n\t\t\t\t\tmessage: e.message,\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\t// If headers were already sent dont't send a second error response\n\t\t\t\tres.end();\n\t\t\t}\n\t\t}\n\t}\n\n\t@Post('/chat', { ipRateLimit: { limit: 100 } })\n\tasync chat(req: AuthenticatedRequest, res: FlushableResponse, @Body payload: AiChatRequestDto) {\n\t\ttry {\n\t\t\tconst abortController = new AbortController();\n\t\t\tconst { signal } = abortController;\n\n\t\t\tconst handleClose = () => abortController.abort();\n\t\t\tres.on('close', handleClose);","sourceCodeStart":118,"sourceCodeEnd":154,"githubUrl":"https://github.com/n8n-io/n8n/blob/5ac6606e81f67bb9534255570cd4e86fd8101eee/packages/cli/src/controllers/ai.controller.ts#L118-L154","documentation":"Returned as HTTP 500 `{ code: 500, message: e.message }` from the AI Assistant `/chat` (or stream-style) endpoint when an error occurs BEFORE streaming begins (headers not yet sent). The catch asserts `e instanceof Error` then sends the native message. If headers were already sent, it just ends the response to avoid a double-write.","triggerScenarios":"The upstream AI SDK fails during request setup (auth, payload validation, network DNS, model unavailable) before any chunk is streamed; an unexpected throw inside `aiService` prior to the first `res.write`.","commonSituations":"AI provider outage; misconfigured AI credentials (`N8N_AI_*`); SDK version mismatch; request payload triggers an internal assertion.","solutions":["Check the server logs for the full stack trace of the underlying `e`.","Verify AI provider credentials and connectivity from the n8n host.","Update `@n8n/ai-assistant-*` packages to a version compatible with the SDK.","Retry — transient provider 5xxs are common."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { await api.post('/ai/...', payload); } catch (e) { if (e.response?.status === 500) { logAiConfigDiagnostics(); await retryWithBackoff(); } else throw e; }","preventionTips":["Validate AI credentials and provider connectivity in a startup health check.","Keep AI assistant package versions aligned with the backend SDK."],"tags":["api","ai-assistant","rest","internal-error"],"backgroundTag":null,"analyzedSha":"5ac6606e81f67bb9534255570cd4e86fd8101eee","analyzedAt":"2026-08-12T05:26:35.080Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}