{"record":{"id":"93d01b01209b0c07","repo":"Budibase/budibase","slug":"invalid-interaction-summary-response","errorCode":null,"errorMessage":"Invalid interaction summary response","messagePattern":"Invalid interaction summary response","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/server/src/sdk/workspace/ai/agentRequests/helpers.ts","lineNumber":271,"sourceCode":"  const llm = await sdk.ai.llm.createLLM(\n    agent.aiconfig,\n    sessionId,\n    undefined,\n    agentId\n  )\n  const result = await generateText({\n    model: llm.chat,\n    providerOptions: llm.providerOptions?.(false),\n    headers: {\n      \"x-litellm-tags\": \"bb-agent-request-interaction-summary\",\n    },\n    instructions: `Summarize the user's intent in this single message for a UI timeline entry. Write it in third person starting with \"User\", e.g. \"User asked about VPN access\". Return plain text only. Use 4 to 6 words, no quotes, no punctuation unless necessary.`,\n    prompt: latestPrompt,\n  })\n\n  const summary = normalizeTitle(result.text || \"\")\n  if (!summary) {\n    throw new Error(\"Invalid interaction summary response\")\n  }\n\n  return summary\n}\n\nexport interface RequestOutcomeDecision {\n  status: \"completed\" | \"failed\"\n  reason: string\n}\n\nconst summarizeActionForOutcome = (action: AgentRequestAction) => {\n  switch (action.type) {\n    case \"user_message\":\n      return { type: action.type, summary: action.summary }\n    case \"tool_call\":\n      return {\n        type: action.type,\n        tool: action.readableName || action.toolName,","sourceCodeStart":253,"sourceCodeEnd":289,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/server/src/sdk/workspace/ai/agentRequests/helpers.ts#L253-L289","documentation":"generateInteractionSummary asks the LLM to produce a short third-person title (4-6 words) of the user's message for the agent-request timeline UI. The LLM's text is passed through normalizeTitle (strips quotes/punctuation/whitespace); if the sanitized result is empty, the response is treated as unusable and this error is thrown. It guards the timeline against blank titles produced by empty prompt input, refusal replies, or model misbehavior.","triggerScenarios":"Calling generateInteractionSummary({latestPrompt, agentId, sessionId}) when: (1) latestPrompt is empty/whitespace-only so the model has nothing to summarize, (2) the LLM returns an empty or refusal-only text (e.g. quota exhausted, filtered content), (3) normalizeTitle strips everything from the reply (e.g. reply was only quotes/punctuation or a JSON wrapper the normalizer discards).","commonSituations":"AI provider misconfiguration (agent.aiconfig pointing at a broken LiteLLM route) causing empty completions; a user sending an emoji-only or whitespace message; model asked to summarize a prompt containing only quotes; provider returning a refusal string that normalizes to nothing.","solutions":["Validate latestPrompt is non-empty (after trim) before calling generateInteractionSummary","Check the agent's aiconfig and the LiteLLM route are healthy (a real completion should come back for a normal prompt)","Retry the summary generation once; LLM empty replies are often transient","Inspect the raw result.text in logs to see whether the model refused or returned an unparseable format, and adjust the instructions/model"],"exampleFix":"// before\ngenerateInteractionSummary({ latestPrompt, agentId, sessionId })\n// after\nif (!latestPrompt.trim()) {\n  latestPrompt = \"(empty message)\"\n}\nawait generateInteractionSummary({ latestPrompt, agentId, sessionId })","handlingStrategy":"fallback","validationCode":"if (!latestPrompt || !latestPrompt.trim()) {\n  throw new Error(\"Cannot summarize an empty prompt\")\n}","typeGuard":null,"tryCatchPattern":"let title\ntry {\n  title = await generateInteractionSummary({ latestPrompt, agentId, sessionId })\n} catch {\n  title = \"User sent a message\" // safe fallback for the timeline entry\n}","preventionTips":["Never pass empty/whitespace prompts to summary generation","Keep the agent's aiconfig pointing at a healthy, instruction-following model","Log raw LLM output when summaries fail so you can see refusals vs empties","Treat timeline titles as best-effort and always provide a fallback string"],"tags":["ai","llm","validation"],"backgroundTag":"invalid-llm-response","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}