{"record":{"id":"5906bebd953bbae2","repo":"MemPalace/mempalace","slug":"embedding-api-request-to-self-url-failed-e","errorCode":null,"errorMessage":"Embedding API request to {self._url} failed: {e}. Check that the server is reachable and MEMPALACE_EMBEDDING_API_URL / embedding_api_url is correct.","messagePattern":"Embedding API request to (.+?) failed: (.+?)\\. Check that the server is reachable and MEMPALACE_EMBEDDING_API_URL / embedding_api_url is correct\\.","errorType":"exception","errorClass":"EmbeddingAPIError","httpStatus":null,"severity":"error","filePath":"mempalace/embedding.py","lineNumber":558,"sourceCode":"        if self._api_key:\n            headers[\"Authorization\"] = f\"Bearer {self._api_key}\"\n\n        out: list = []\n        texts = list(input)\n        for start in range(0, len(texts), _EF_API_BATCH):\n            batch = texts[start : start + _EF_API_BATCH]\n            # encoding_format=float is explicit so a server that defaults to\n            # base64 doesn't hand back strings we'd mis-parse as vectors.\n            payload = {\"model\": self._model, \"input\": batch, \"encoding_format\": \"float\"}\n            req = Request(self._url, data=json.dumps(payload).encode(\"utf-8\"), headers=headers)\n            try:\n                with urlopen(req, timeout=_EF_API_TIMEOUT) as resp:\n                    data = json.loads(resp.read())\n            # ValueError covers an invalid/missing URL scheme and json.JSONDecodeError;\n            # http.client.HTTPException covers low-level protocol faults (BadStatusLine,\n            # IncompleteRead) common with local/overloaded servers.\n            except (HTTPError, URLError, OSError, http.client.HTTPException, ValueError) as e:\n                raise EmbeddingAPIError(\n                    f\"Embedding API request to {self._url} failed: {e}. Check that the \"\n                    f\"server is reachable and MEMPALACE_EMBEDDING_API_URL / embedding_api_url \"\n                    f\"is correct.\"\n                ) from e\n            out.extend(self._vectors_from_response(data, len(batch)))\n        return out\n\n    def _vectors_from_response(self, data, n: int) -> list:\n        \"\"\"Validate one ``/v1/embeddings`` response and return L2-normed vectors.\n\n        Guards every way a non-conformant server could corrupt the store\n        silently: a missing/short ``data`` array, response ``index`` values\n        that aren't the contiguous ``0..n-1`` batch positions (sorting then\n        zipping positionally would otherwise misalign vectors with texts), and\n        malformed / ragged / base64 embedding payloads. All failures raise\n        :class:`EmbeddingAPIError` naming the endpoint rather than a cryptic\n        numpy error — a silent wrong result would break the 100%-recall promise.\n        \"\"\"","sourceCodeStart":540,"sourceCodeEnd":576,"githubUrl":"https://github.com/MemPalace/mempalace/blob/06cb6987f02610784fefbad4b2bd5d026d164ba6/mempalace/embedding.py#L540-L576","documentation":"Raised by the OpenAI-compatible embedding client when the HTTP POST to self._url fails at the transport layer. It catches a deliberately wide net — HTTPError, URLError, OSError, http.client.HTTPException, and ValueError (invalid URL scheme or JSON decode of the response body) — because local/self-hosted servers (LM Studio, llama.cpp, vLLM, Ollama) commonly produce low-level protocol faults. The message names the URL and both config surfaces (MEMPALACE_EMBEDDING_API_URL env var / embedding_api_url in ~/.mempalace/config.json) so the user can correct the endpoint.","triggerScenarios":"embedding_model='openai-compat' is configured and the server is down, the URL has a typo or wrong port, the URL lacks a scheme (ValueError path), the server returns non-JSON over HTTP 200, or the server drops the connection mid-response (IncompleteRead) under load. Timeout is _EF_API_TIMEOUT, so a hung server also lands here.","commonSituations":"LM Studio or Ollama not started before running mempalace; pointing at the chat completions port instead of the embeddings port; using https:// against a plain-HTTP local server; corporate proxies intercepting localhost; server overloaded so reads time out; URL configured as 'host:port' without http://.","solutions":["Verify the server is up: curl -s http://host:port/v1/embeddings -d '{\"model\":\"x\",\"input\":[\"hi\"]}' -H 'Content-Type: application/json'","Check the configured URL matches the server's embeddings endpoint, including scheme and port: MEMPALACE_EMBEDDING_API_URL=http://127.0.0.1:1234 (must include http://)","If the server was slow to start (first model load), wait for it to finish loading and retry","Disable proxying for localhost if a corporate proxy is set: export NO_PROXY=localhost,127.0.0.1","For IncompleteRead/BadStatusLine under load, reduce concurrent mempalace operations or raise the server's worker capacity"],"exampleFix":"# before\nexport MEMPALACE_EMBEDDING_API_URL=127.0.0.1:1234  # missing scheme -> ValueError path\n# after\nexport MEMPALACE_EMBEDDING_API_URL=http://127.0.0.1:1234\n\n# retry wrapper\nfrom mempalace.embedding import EmbeddingAPIError\ntry:\n    vecs = ef(texts)\nexcept EmbeddingAPIError as e:\n    if 'failed' in str(e):\n        time.sleep(2); vecs = ef(texts)  # server still warming up","handlingStrategy":"retry","validationCode":"import socket\nfrom urllib.parse import urlparse\n\ndef endpoint_reachable(url: str, timeout: float = 2.0) -> bool:\n    u = urlparse(url)\n    if u.scheme not in (\"http\", \"https\") or not u.hostname:\n        return False\n    with socket.socket() as s:\n        s.settimeout(timeout)\n        return s.connect_ex((u.hostname, u.port or (443 if u.scheme == 'https' else 80))) == 0","typeGuard":null,"tryCatchPattern":"from mempalace.embedding import EmbeddingAPIError\nimport time\n\nfor attempt in range(3):\n    try:\n        vecs = ef(texts)\n        break\n    except EmbeddingAPIError as e:\n        if attempt == 2 or \"non-object\" in str(e) or \"malformed\" in str(e):\n            raise  # only retry transport faults, not schema errors\n        time.sleep(2 ** attempt)  # server may still be loading its model","preventionTips":["Health-check the embedding server before starting bulk ingest","Always include the scheme in MEMPALACE_EMBEDDING_API_URL (http://...)","Set NO_PROXY=localhost,127.0.0.1 when a corporate proxy is present","Give local servers time to load the model on first request; warm them with a one-text request"],"tags":["network","embedding","http","api","config"],"backgroundTag":null,"analyzedSha":"06cb6987f02610784fefbad4b2bd5d026d164ba6","analyzedAt":"2026-08-15T03:03:36.213Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}