{"record":{"id":"d0947f02036c5098","repo":"danny-avila/LibreChat","slug":"validation-error-message","errorCode":null,"errorMessage":"${validation.error?.message}","messagePattern":"\\$\\{validation\\.error\\?\\.message\\}","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/api/src/agents/discovery.ts","lineNumber":256,"sourceCode":"\n    if (!hasAccess) {\n      logger.warn(\n        `[discoverConnectedAgents] User ${userId} lacks VIEW access to handoff agent ${agentId}, skipping`,\n      );\n      markSkipped(agentId);\n      return null;\n    }\n\n    const validation = await validateAgentModel({\n      req,\n      res,\n      agent,\n      modelsConfig,\n      logViolation,\n    });\n\n    if (!validation.isValid) {\n      throw new Error(validation.error?.message);\n    }\n\n    /**\n     * Force `endpoint: agents` on the per-sub-agent init call so\n     * `initializeAgent`'s `isAgentsEndpoint`-gated `allowedProviders`\n     * check always fires for handoff sub-agents, regardless of which\n     * endpoint the caller entered through. Without this, the OpenAI-\n     * compat routes (whose `endpointOption.endpoint` is the primary\n     * provider, not `agents`) would silently bypass the provider\n     * allowlist configured under `endpoints.agents.allowedProviders`.\n     */\n    const subAgentEndpointOption: Partial<TEndpointOption> = {\n      ...(endpointOption ?? {}),\n      endpoint: EModelEndpoint.agents,\n    };\n\n    const scopedSkillIds = computeAccessibleSkillIds?.(agent);\n    const config = await initializeAgent(","sourceCodeStart":238,"sourceCodeEnd":274,"githubUrl":"https://github.com/danny-avila/LibreChat/blob/5ff282f9006c436e561de1afd39a481bea1ef0d8/packages/api/src/agents/discovery.ts#L238-L274","documentation":"discoverConnectedAgents validates each handoff sub-agent's model configuration via validateAgentModel. If validation.isValid is false, the error message from validation.error is re-thrown. Note: because the throw uses validation.error?.message, if error itself is undefined the thrown Error will have message 'undefined' — so a missing error object produces a confusing message.","triggerScenarios":"An agent referenced as a handoff sub-agent whose model configuration is invalid: missing model, mismatched provider, model not in the allowedProviders list, or endpointOption.endpoint not permitted by endpoints.agents.allowedProviders.","commonSituations":"An agent saved with a model id that was later removed from the provider; sub-agent's provider not in the agents allowlist; OpenAI-compat route used to reach an agent whose handoff target is on a disallowed provider; deleted API key for the sub-agent's provider.","solutions":["Inspect validation.error.message in the logs (or reproduce via validateAgentModel directly) to see the specific model/provider violation.","Correct the sub-agent's model and provider in the agent definition to one allowed by endpoints.agents.allowedProviders.","Add the missing provider/model to the allowedProviders config if the restriction is too tight.","If validation.error is undefined in your logs, the agent definition is in an unexpected state — re-save it."],"exampleFix":"// before — rethrow loses context when error is undefined\nif (!validation.isValid) {\n  throw new Error(validation.error?.message);\n}\n\n// after — surface a clear message and keep the cause\nif (!validation.isValid) {\n  throw new Error(\n    validation.error?.message ?? `Agent ${agent._id} failed model validation`,\n    { cause: validation.error },\n  );\n}","handlingStrategy":"try-catch","validationCode":"// pre-validate sub-agent model before discovery\nconst v = await validateAgentModel({ req, res, agent, modelsConfig, logViolation });\nif (!v.isValid) {\n  throw new Error(v.error?.message ?? `Agent ${agent._id} failed model validation`);\n}","typeGuard":"const hasModelViolation = (e: unknown): boolean =>\n  e instanceof Error && /model|provider|allowedProviders/i.test(e.message);","tryCatchPattern":"try {\n  await discoverConnectedAgents({ ... });\n} catch (error) {\n  if (error instanceof Error && /model|provider|allowedProviders/i.test(error.message)) {\n    res.status(400).json({ error: `Handoff sub-agent misconfigured: ${error.message}` });\n    return;\n  }\n  throw error;\n}","preventionTips":["Keep each handoff sub-agent's model/provider inside endpoints.agents.allowedProviders.","When removing a model from a provider, audit agents that reference it.","Re-save agent definitions after provider/key changes."],"tags":["agents","validation","model-config","handoff","provider-allowlist"],"backgroundTag":null,"analyzedSha":"5ff282f9006c436e561de1afd39a481bea1ef0d8","analyzedAt":"2026-08-12T21:38:08.145Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}