{"record":{"id":"590e53aa1d7c7b3e","repo":"Mintplex-Labs/anything-llm","slug":"no-apipie-llm-api-key-was-set","errorCode":null,"errorMessage":"No ApiPie LLM API key was set.","messagePattern":"No ApiPie LLM API key was set\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"server/utils/AiProviders/apipie/index.js","lineNumber":24,"sourceCode":"  formatChatHistory,\n} = require(\"../../helpers/chat/responses\");\nconst fs = require(\"fs\");\nconst path = require(\"path\");\nconst { safeJsonParse } = require(\"../../http\");\nconst {\n  LLMPerformanceMonitor,\n} = require(\"../../helpers/chat/LLMPerformanceMonitor\");\n\nconst cacheFolder = path.resolve(\n  process.env.STORAGE_DIR\n    ? path.resolve(process.env.STORAGE_DIR, \"models\", \"apipie\")\n    : path.resolve(__dirname, `../../../storage/models/apipie`)\n);\n\nclass ApiPieLLM {\n  constructor(embedder = null, modelPreference = null) {\n    if (!process.env.APIPIE_LLM_API_KEY)\n      throw new Error(\"No ApiPie LLM API key was set.\");\n\n    this.className = \"ApiPieLLM\";\n    const { OpenAI: OpenAIApi } = require(\"openai\");\n    this.basePath = \"https://apipie.ai/v1\";\n    this.openai = new OpenAIApi({\n      baseURL: this.basePath,\n      apiKey: process.env.APIPIE_LLM_API_KEY ?? null,\n    });\n    this.model =\n      modelPreference ||\n      process.env.APIPIE_LLM_MODEL_PREF ||\n      \"openrouter/mistral-7b-instruct\";\n    this.limits = {\n      history: this.promptWindowLimit() * 0.15,\n      system: this.promptWindowLimit() * 0.15,\n      user: this.promptWindowLimit() * 0.7,\n    };\n","sourceCodeStart":6,"sourceCodeEnd":42,"githubUrl":"https://github.com/Mintplex-Labs/anything-llm/blob/526360e320da9d1b36074be5ed64fe76e5bbfbbd/server/utils/AiProviders/apipie/index.js#L6-L42","documentation":"Thrown by the ApiPieLLM constructor when process.env.APIPIE_LLM_API_KEY is falsy. ApiPie is an OpenAI-compatible aggregator, so an API key is mandatory before any chat completion or stream call. Like other provider constructors, it fails fast so downstream code never runs without credentials.","triggerScenarios":"Selecting the ApiPie provider and triggering a chat/embed while APIPIE_LLM_API_KEY is unset. The constructor reads the key directly from process.env and also applies a `?? null` fallback when building the OpenAI client, but the guard above already aborts construction first.","commonSituations":"ApiPie account not yet created / key not copied into .env; key stored under a differently-named variable; multi-instance deploy where only one node has the env; .env updated but process not restarted.","solutions":["Set `APIPIE_LLM_API_KEY=<your apipie key>` in .env and restart the server.","Re-save the ApiPie provider credentials via the UI so AnythingLLM persists them to .env.","Confirm the env is visible to the process: `printenv APIPIE_LLM_API_KEY` in the same context the server runs.","Optionally also set APIPIE_LLM_MODEL_PREF to avoid the default `openrouter/mistral-7b-instruct` fallback."],"exampleFix":"// before\n// .env\nAPIPIE_LLM_API_KEY=\n\n// after\n// .env\nAPIPIE_LLM_API_KEY=apipie-xxxxxxxxxxxxxxxx\nAPIPIE_LLM_MODEL_PREF=openrouter/mistral-7b-instruct","handlingStrategy":"validation","validationCode":"if (!process.env.APIPIE_LLM_API_KEY) {\n  throw new Error(\n    \"APIPIE_LLM_API_KEY is missing. Set it before selecting the ApiPie provider.\"\n  );\n}\nconst llm = new ApiPieLLM(embedder, modelPref);","typeGuard":"/** @param {unknown} v @returns {boolean} */\nfunction isNonEmptyKey(v) {\n  return typeof v === \"string\" && v.trim().length > 0;\n}","tryCatchPattern":"try {\n  const llm = new ApiPieLLM(embedder, modelPref);\n} catch (e) {\n  if (/No ApiPie LLM API key/.test(e.message)) {\n    return { ok: false, reason: \"missing-api-key\" };\n  }\n  throw e;\n}","preventionTips":["Centralize provider-credential validation so the same check runs in UI save and at construction.","Refuse to mark a provider 'configured' in the UI until its required env vars are present.","Restart the server (or hot-reload .env) after credential edits so dotenv picks up changes.","Use exact env var names from a shared constants file to avoid typos."],"tags":["config","env","authentication","apipie","constructor"],"backgroundTag":null,"analyzedSha":"526360e320da9d1b36074be5ed64fe76e5bbfbbd","analyzedAt":"2026-08-13T01:45:47.170Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}