{"record":{"id":"e2b5473df67d040e","repo":"Mintplex-Labs/anything-llm","slug":"res-statustext-error-fetching-api-keys","errorCode":null,"errorMessage":"res.statusText || \"Error fetching api keys.\"","messagePattern":"res\\.statusText \\|\\| \"Error fetching api keys\\.\"","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"frontend/src/models/admin.js","lineNumber":199,"sourceCode":"      headers: baseHeaders(),\n      body: JSON.stringify(updates),\n    })\n      .then((res) => res.json())\n      .catch((e) => {\n        console.error(e);\n        return { success: false, error: e.message };\n      });\n  },\n\n  // API Keys\n  getApiKeys: async function () {\n    return fetch(`${API_BASE}/admin/api-keys`, {\n      method: \"GET\",\n      headers: baseHeaders(),\n    })\n      .then((res) => {\n        if (!res.ok) {\n          throw new Error(res.statusText || \"Error fetching api keys.\");\n        }\n        return res.json();\n      })\n      .catch((e) => {\n        console.error(e);\n        return { apiKeys: [], error: e.message };\n      });\n  },\n  generateApiKey: async function (data = {}) {\n    return fetch(`${API_BASE}/admin/generate-api-key`, {\n      method: \"POST\",\n      headers: baseHeaders(),\n      body: JSON.stringify(data),\n    })\n      .then((res) => {\n        if (!res.ok) {\n          throw new Error(res.statusText || \"Error generating api key.\");\n        }","sourceCodeStart":181,"sourceCodeEnd":217,"githubUrl":"https://github.com/Mintplex-Labs/anything-llm/blob/3aec848f2885144aa8f1e53b9731a04310d5d558/frontend/src/models/admin.js#L181-L217","documentation":"The Qdrant twin of the Pinecone guard: performSimilaritySearch requires a namespace, a non-empty input, and an LLMConnector to embed the query; any falsy value throws before touching Qdrant. Note the behavioral difference downstream: for a merely non-existent namespace the Qdrant provider returns an empty result with a message instead of throwing, so this specific throw is strictly about missing/empty arguments.","triggerScenarios":"Custom code calling performSimilaritySearch({ namespace }) with no input; input: '' or whitespace after trimming; LLMConnector null because no embedding engine is configured (missing API key for the selected engine); plugins constructing the argument object manually with wrong keys.","commonSituations":"Plugins/scripts invoking the provider directly; embedding engine unset or its key removed after workspaces existed; blank chat input reaching the search layer after a refactor; renamed argument fields during upgrades.","solutions":["Supply all three fields: { namespace, input: input.trim(), LLMConnector } with a non-empty input.","If hit during normal chat, configure and save a working embedding engine first — LLMConnector is null when none resolves.","Validate/trim the prompt upstream so blank inputs never reach the search call.","For a missing-namespace case you will not get this throw (Qdrant returns empty results) — focus on the argument contract itself."],"exampleFix":"// before\nconst r = await vectorDB.performSimilaritySearch({ namespace, input: '' });\n\n// after\nif (!namespace) throw new Error('namespace required');\nif (!input?.trim()) return { contextTexts: [], sources: [], message: 'Empty query' };\nconst LLMConnector = getEmbeddingEngineSelection();\nif (!LLMConnector) throw new Error('No embedding engine configured');\nconst r = await vectorDB.performSimilaritySearch({ namespace, input: input.trim(), LLMConnector });","handlingStrategy":"type-guard","validationCode":"const missing = [!namespace && 'namespace', !input?.trim() && 'input', !LLMConnector && 'LLMConnector'].filter(Boolean);\nif (missing.length > 0) {\n  throw new Error(`performSimilaritySearch missing: ${missing.join(', ')}`);\n}\nawait vectorDB.performSimilaritySearch({ namespace, input: input.trim(), LLMConnector });","typeGuard":"function isSimilaritySearchRequest(req) {\n  return (\n    req !== null && typeof req === 'object' &&\n    typeof req.namespace === 'string' && req.namespace.length > 0 &&\n    typeof req.input === 'string' && req.input.trim().length > 0 &&\n    req.LLMConnector != null && typeof req.LLMConnector.embedTextInput === 'function'\n  );\n}","tryCatchPattern":"try {\n  const r = await vectorDB.performSimilaritySearch({ namespace, input, LLMConnector });\n} catch (e) {\n  if (/Invalid request to performSimilaritySearch/.test(e.message)) {\n    // argument-contract bug in the caller; note Qdrant returns empty results (no throw) for missing namespaces\n    return { contextTexts: [], sources: [], message: 'Invalid search request' };\n  }\n  throw e;\n}","preventionTips":["Use the built-in chat pipeline; it constructs { namespace, input, LLMConnector } correctly.","Guard custom calls with isSimilaritySearchRequest before invoking.","Ensure an embedding engine is configured — a null LLMConnector is a config failure, not transient.","Trim and reject blank inputs upstream of RAG."],"tags":["qdrant","rag","similarity-search","request-validation","embedding-engine"],"backgroundTag":"missing-required-argument","analyzedSha":"3aec848f2885144aa8f1e53b9731a04310d5d558","analyzedAt":"2026-08-18T10:02:21.017Z","contentChangedAt":"2026-08-18T10:02:21.017Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}