{"record":{"id":"8483325b27de76a8","repo":"Budibase/budibase","slug":"invalid-agent-request-link-response-unknown-reque","errorCode":null,"errorMessage":"Invalid agent request link response: unknown requestId \"${decision.requestId}\"","messagePattern":"Invalid agent request link response: unknown requestId \"(.+?)\"","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/server/src/sdk/workspace/ai/agentRequests/helpers.ts","lineNumber":140,"sourceCode":"  } catch (error) {\n    console.error(\"Failed to analyze agent request link\", {\n      agentId,\n      sessionId,\n      error,\n    })\n    throw error\n  }\n\n  const decision = extractJson(result.text || \"\")\n  if (!decision) {\n    throw new Error(\"Invalid agent request link response\")\n  }\n\n  if (\n    decision.decision === \"existing_thread\" &&\n    !candidateRequests.some(request => request._id === decision.requestId)\n  ) {\n    throw new Error(\n      `Invalid agent request link response: unknown requestId \"${decision.requestId}\"`\n    )\n  }\n\n  return {\n    decision: decision.decision,\n    requestId: decision.requestId,\n    entryAction: decision.entryAction,\n  }\n}\n\nexport async function generateAgentRequestTitle({\n  latestPrompt,\n  agentId,\n  sessionId,\n  operation,\n}: {\n  latestPrompt: string","sourceCodeStart":122,"sourceCodeEnd":158,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/server/src/sdk/workspace/ai/agentRequests/helpers.ts#L122-L158","documentation":"After parsing the LLM link decision, analyzeAgentRequestLink verifies that a decision of \"existing_thread\" references a requestId actually present in candidateRequests. If the model hallucinates or returns a requestId not among the candidates, it throws Error(`Invalid agent request link response: unknown requestId \"${decision.requestId}\"`).","triggerScenarios":"The LLM returns {\"decision\":\"existing_thread\",\"requestId\":\"...\"} where the ID is fabricated, from another session, truncated, or not in the candidate list passed to the function.","commonSituations":"Hallucinated IDs from smaller models; candidates filtered down between analysis and validation; the model echoing an ID from recentChatContext instead of candidateRequests.","solutions":["Catch the error and fall back to decision \"new_thread\"","Retry the analysis call; if it recurs, disable request linking for the model config","Use a stronger model that respects the candidate list, or include only clearly-labeled candidate IDs in the prompt"],"exampleFix":"// before\nconst analysis = await analyzeAgentRequestLink({ candidateRequests, ... })\n// after\nlet analysis\ntry {\n  analysis = await analyzeAgentRequestLink({ candidateRequests, ... })\n} catch {\n  analysis = { decision: \"new_thread\" }\n}","handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"let analysis\ntry {\n  analysis = await analyzeAgentRequestLink({ latestPrompt, candidateRequests, ... })\n} catch (err) {\n  if (err instanceof Error && err.message.includes(\"unknown requestId\")) {\n    analysis = { decision: \"new_thread\" }\n  } else {\n    throw err\n  }\n}","preventionTips":["Explicitly label candidate requestIds in the prompt and instruct the model to choose only from them","Use stronger models less prone to hallucinating IDs","Treat unknown requestId as new_thread instead of failing the user request"],"tags":["llm","hallucination","response-validation","agent-requests"],"backgroundTag":"llm-hallucinated-identifier","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}