{"record":{"id":"b8798020ab812eb3","repo":"danny-avila/LibreChat","slug":"req-baseurl-invalid-version-version","errorCode":null,"errorMessage":"[${req.baseUrl}] Invalid version: ${version}","messagePattern":"\\[(.+?)\\] Invalid version: (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"api/server/controllers/assistants/helpers.js","lineNumber":30,"sourceCode":"const { getEndpointsConfig } = require('~/server/services/Config');\n\n/**\n * @param {ServerRequest} req\n * @param {string} [endpoint]\n * @returns {Promise<string>}\n */\nconst getCurrentVersion = async (req, endpoint) => {\n  const index = req.baseUrl.lastIndexOf('/v');\n  let version = index !== -1 ? req.baseUrl.substring(index + 1, index + 3) : null;\n  if (!version && req.body.version) {\n    version = `v${req.body.version}`;\n  }\n  if (!version && endpoint) {\n    const endpointsConfig = await getEndpointsConfig(req);\n    version = `v${endpointsConfig?.[endpoint]?.version ?? defaultAssistantsVersion[endpoint]}`;\n  }\n  if (!version?.startsWith('v') && version.length !== 2) {\n    throw new Error(`[${req.baseUrl}] Invalid version: ${version}`);\n  }\n  return version;\n};\n\n/**\n * Asynchronously lists assistants based on provided query parameters.\n *\n * Initializes the client with the current request and response objects and lists assistants\n * according to the query parameters. This function abstracts the logic for non-Azure paths.\n *\n * @deprecated\n * @async\n * @param {object} params - The parameters object.\n * @param {object} params.req - The request object, used for initializing the client.\n * @param {object} params.res - The response object, used for initializing the client.\n * @param {string} params.version - The API version to use.\n * @param {object} params.query - The query parameters to list assistants (e.g., limit, order).\n * @returns {Promise<object>} A promise that resolves to the response from the `openai.beta.assistants.list` method call.","sourceCodeStart":12,"sourceCodeEnd":48,"githubUrl":"https://github.com/danny-avila/LibreChat/blob/5ff282f9006c436e561de1afd39a481bea1ef0d8/api/server/controllers/assistants/helpers.js#L12-L48","documentation":"Thrown by getCurrentVersion while initializing an Assistants API client. The version token (expected as 'v1' or 'v2') is resolved from, in order: the '/v' segment of req.baseUrl, req.body.version (prefixed with 'v'), or the endpoint config's version field. If the resolved value neither starts with 'v' nor is exactly two characters, it is treated as malformed and rejected. This guards the OpenAI-Beta 'assistants=vN' header from carrying a bad value.","triggerScenarios":"A request whose baseUrl contains a '/v' fragment that yields a non-conforming substring (e.g. '/v' at the very end, or '/vX' where X is missing), combined with no usable req.body.version and no endpoint config default. Also fires when a caller sends req.body.version as an already-prefixed or malformed string that survives into a branch that does not re-prefix it.","commonSituations":"Reverse proxy or custom route prefix that rewrites the '/api/assistants/...' path and breaks the '/v' token; clients hitting a stale endpoint URL after an Assistants v1->v2 migration; a misconfigured endpoint record whose version field is empty or non-numeric.","solutions":["Ensure the request URL contains a clean version segment like /v1 or /v2 (verify req.baseUrl with a log before the call).","Send version as the bare numeric in req.body.version ('1' or '2') so the code can prefix it with 'v'.","Confirm the endpoint has a version set in the endpoints config or a defaultAssistantsVersion fallback for that endpoint key.","If routing through a proxy, rewrite paths so the '/vN' segment is preserved verbatim."],"exampleFix":"// before: POST /api/assistants/v   (trailing /v, malformed)\n// after:  POST /api/assistants/v2","handlingStrategy":"validation","validationCode":"function resolveVersion(baseUrl, bodyVersion, endpointVersion) {\n  const idx = baseUrl.lastIndexOf('/v');\n  let v = idx !== -1 ? baseUrl.substring(idx + 1, idx + 3) : null;\n  if (!v && bodyVersion) v = `v${bodyVersion}`;\n  if (!v && endpointVersion) v = `v${endpointVersion}`;\n  if (!v || !/^v\\d$/.test(v)) {\n    throw new Error(`Refusing request: invalid version '${v}'`);\n  }\n  return v;\n}","typeGuard":"function isValidAssistantsVersion(v) {\n  return typeof v === 'string' && /^v\\d$/.test(v);\n}","tryCatchPattern":"try { await getOpenAIClient({ req, res }); }\ncatch (e) { if (/Invalid version/.test(e.message)) { return res.status(400).json({ error: 'Unsupported Assistants API version' }); } throw e; }","preventionTips":["Always send a clean /vN segment in the assistants route URL.","Keep a version default in the endpoints config as a last-resort fallback.","Add an integration test that posts against a known-good /v2 URL."],"tags":["assistants","versioning","configuration","openai"],"backgroundTag":null,"analyzedSha":"5ff282f9006c436e561de1afd39a481bea1ef0d8","analyzedAt":"2026-08-12T21:38:08.145Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}