{"record":{"id":"cd8c510cdb9fd584","repo":"ruvnet/ruflo","slug":"openai-base-url-not-set","errorCode":null,"errorMessage":"OPENAI_BASE_URL not set","messagePattern":"OPENAI_BASE_URL not set","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"ruflo/src/ruvocal/src/lib/server/models.ts","lineNumber":302,"sourceCode":"\t\t{\n\t\t\ttotal: summary.total,\n\t\t\tadded: summary.added,\n\t\t\tremoved: summary.removed,\n\t\t\tchanged: summary.changed,\n\t\t\tdurationMs: summary.durationMs,\n\t\t},\n\t\t\"[models] Model cache refreshed\"\n\t);\n\n\treturn summary;\n};\n\nconst buildModels = async (): Promise<ProcessedModel[]> => {\n\tif (!openaiBaseUrl) {\n\t\tlogger.error(\n\t\t\t\"OPENAI_BASE_URL is required. Set it to an OpenAI-compatible base (e.g., https://router.huggingface.co/v1).\"\n\t\t);\n\t\tthrow new Error(\"OPENAI_BASE_URL not set\");\n\t}\n\n\ttry {\n\t\tconst baseURL = openaiBaseUrl;\n\t\tlogger.info({ baseURL }, \"[models] Using OpenAI-compatible base URL\");\n\n\t\t// Canonical auth token is OPENAI_API_KEY; keep HF_TOKEN as legacy alias\n\t\tconst authToken = config.OPENAI_API_KEY || config.HF_TOKEN;\n\n\t\t// Use auth token from the start if available to avoid rate limiting issues\n\t\t// Some APIs rate-limit unauthenticated requests more aggressively\n\t\tconst response = await fetch(`${baseURL}/models`, {\n\t\t\theaders: authToken ? { Authorization: `Bearer ${authToken}` } : undefined,\n\t\t});\n\t\tlogger.info({ status: response.status }, \"[models] First fetch status\");\n\t\tif (!response.ok && response.status === 401 && !authToken) {\n\t\t\t// If we get 401 and didn't have a token, there's nothing we can do\n\t\t\tthrow new Error(","sourceCodeStart":284,"sourceCodeEnd":320,"githubUrl":"https://github.com/ruvnet/ruflo/blob/fa13ee4ad60ac2090b1480656eb233521790d640/ruflo/src/ruvocal/src/lib/server/models.ts#L284-L320","documentation":"Thrown by buildModels() in models.ts before any network call. The whole app speaks exclusively to OpenAI-compatible APIs, and openaiBaseUrl (from the OPENAI_BASE_URL env var) is mandatory to locate the /models endpoint; without it there is no upstream to query, so the model registry can never be built and the error is fatal to model loading.","triggerScenarios":"Server starts with OPENAI_BASE_URL unset or empty (env file not copied to .env.local, variable dropped in the deploy environment, or name typo like OPENAI_BASEURL). Every refreshModels() call fails immediately at this guard.","commonSituations":"Fresh clone where .env was copied to .env.local but the variable left blank; container/CI deployment that does not forward the env var; renaming or removing the variable after upgrading to a version that dropped legacy fallbacks.","solutions":["Set OPENAI_BASE_URL in .env.local (or the process environment) to an OpenAI-compatible base, e.g. https://router.huggingface.co/v1 or http://localhost:11434/v1.","Restart the dev/prod server after changing env files — SvelteKit only reads them at boot.","Confirm the variable is actually exported in the runtime: printenv OPENAI_BASE_URL in the same shell/container that runs the app.","Check for typos and trailing whitespace in the env file."],"exampleFix":"# .env.local (before)\n# (OPENAI_BASE_URL missing)\n\n# .env.local (after)\nOPENAI_BASE_URL=https://router.huggingface.co/v1\nOPENAI_API_KEY=hf_***","handlingStrategy":"validation","validationCode":"if (!process.env.OPENAI_BASE_URL) {\n\tthrow new Error(\"OPENAI_BASE_URL is required (e.g. https://router.huggingface.co/v1)\");\n}","typeGuard":"function isNonEmptyString(v: unknown): v is string {\n\treturn typeof v === \"string\" && v.trim().length > 0;\n}","tryCatchPattern":null,"preventionTips":["Fail fast at boot on missing required env vars instead of first use.","Use a schema (zod) for env parsing so missing vars are listed in one error.","Document required env vars in .env.example and check them in CI."],"tags":["environment","configuration","models","startup"],"backgroundTag":"missing-env-var","analyzedSha":"fa13ee4ad60ac2090b1480656eb233521790d640","analyzedAt":"2026-08-18T21:34:22.708Z","contentChangedAt":"2026-08-18T21:34:22.708Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}