{"record":{"id":"74418026994a5e0d","repo":"decolua/9router","slug":"missing-base-url","errorCode":null,"errorMessage":"Missing base URL","messagePattern":"Missing base URL","errorType":"validation","errorClass":"MissingBaseUrlError","httpStatus":null,"severity":"error","filePath":"open-sse/handlers/embeddingProviders/selfhostedEmbedding.js","lineNumber":40,"sourceCode":"\nexport class MissingBaseUrlError extends Error {\n  constructor() {\n    super(\n      \"Self-hosted Embedding needs an endpoint: set this connection's baseUrl to \" +\n        \"the OpenAI base URL of your server, e.g. http://host:8080/v1 (note the /v1 — \" +\n        \"\\\"/embeddings\\\" is appended to it). Refusing to fall back to api.openai.com, \" +\n        \"which would send your input and API key to OpenAI.\"\n    );\n    this.name = \"MissingBaseUrlError\";\n    this.isConfigError = true;\n  }\n}\n\nexport default {\n  ...baseAdapter,\n  buildUrl: (_model, creds) => {\n    const rawBaseUrl = creds?.providerSpecificData?.baseUrl;\n    if (!rawBaseUrl || !String(rawBaseUrl).trim()) throw new MissingBaseUrlError();\n    // Accept either the OpenAI base or a full embeddings URL, so a value pasted\n    // from a curl example works as well as one typed from the help text.\n    const baseUrl = String(rawBaseUrl).trim().replace(/\\/$/, \"\").replace(/\\/embeddings$/, \"\");\n    return `${baseUrl}/embeddings`;\n  },\n};\n","sourceCodeStart":22,"sourceCodeEnd":47,"githubUrl":"https://github.com/decolua/9router/blob/90b52e06ffd666b7929554211474d01588f6b1f8/open-sse/handlers/embeddingProviders/selfhostedEmbedding.js#L22-L47","documentation":"Raised by the self-hosted embedding adapter's buildUrl (open-sse/handlers/embeddingProviders/selfhostedEmbedding.js:40) as a MissingBaseUrlError when a Self-hosted Embedding connection has no providerSpecificData.baseUrl. Unlike the generic OpenAI-compatible adapter, this adapter deliberately refuses to fall back to https://api.openai.com/v1 — doing so would silently send the user's local embedding input text and API key to OpenAI. An empty baseUrl is treated as a hard configuration error (isConfigError = true).","triggerScenarios":"An embedding request targets the 'selfhosted-embedding' provider and creds.providerSpecificData.baseUrl is undefined, null, or whitespace-only. Typically a connection was saved without filling the endpoint field, or providerSpecificData was dropped during credential import/export.","commonSituations":"User created the connection and left 'Base URL' blank assuming a default exists; baseUrl was cleared when editing other fields; credential JSON migrated from another tool omits providerSpecificData; trailing whitespace-only value pasted into the field.","solutions":["Edit the Self-hosted Embedding connection and set baseUrl to your server's OpenAI-compatible base, e.g. http://localhost:8080/v1 ('/embeddings' is appended automatically).","Include the /v1 segment — the adapter only strips a trailing '/embeddings', it does not add a version path.","If you were re-importing credentials, re-add providerSpecificData: { baseUrl: \"http://host:8080/v1\" } to the credential JSON.","Full/embeddings URLs also work: http://host:8080/v1/embeddings is normalized to the base automatically."],"exampleFix":"// before\n{ \"providerSpecificData\": {} }\n// after\n{ \"providerSpecificData\": { \"baseUrl\": \"http://localhost:8080/v1\" } }","handlingStrategy":"validation","validationCode":"const baseUrl = creds?.providerSpecificData?.baseUrl;\nif (!baseUrl || !String(baseUrl).trim()) {\n  throw new Error(\"Self-hosted Embedding requires providerSpecificData.baseUrl, e.g. http://host:8080/v1\");\n}","typeGuard":"function hasSelfhostedBaseUrl(creds) {\n  const b = creds?.providerSpecificData?.baseUrl;\n  return typeof b === \"string\" && b.trim().length > 0;\n}","tryCatchPattern":"try {\n  await embed(texts);\n} catch (e) {\n  if (e.name === \"MissingBaseUrlError\" || /Missing base URL/.test(e.message)) {\n    openConnectionSettingsAndFocusBaseUrlField();\n  } else throw e;\n}","preventionTips":["Make baseUrl a required field in the connection form for self-hosted providers.","Validate the endpoint with a cheap call (e.g. GET /v1/models) when saving the connection.","Never assume a cloud default — for self-hosted, blank endpoint must block saving.","Include the /v1 path per the field's help text; '/embeddings' is appended automatically."],"tags":["config","missing-base-url","embeddings","self-hosted"],"backgroundTag":"missing-base-url","analyzedSha":"90b52e06ffd666b7929554211474d01588f6b1f8","analyzedAt":"2026-08-30T21:05:45.952Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}