MemPalace/mempalace · error · EmbeddingAPIError

Embedding API request to {self._url} failed: {e}. Check that

Error message

Embedding API request to {self._url} failed: {e}. Check that the server is reachable and MEMPALACE_EMBEDDING_API_URL / embedding_api_url is correct.

What it means

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.

Source

Thrown at mempalace/embedding.py:558

        if self._api_key:
            headers["Authorization"] = f"Bearer {self._api_key}"

        out: list = []
        texts = list(input)
        for start in range(0, len(texts), _EF_API_BATCH):
            batch = texts[start : start + _EF_API_BATCH]
            # encoding_format=float is explicit so a server that defaults to
            # base64 doesn't hand back strings we'd mis-parse as vectors.
            payload = {"model": self._model, "input": batch, "encoding_format": "float"}
            req = Request(self._url, data=json.dumps(payload).encode("utf-8"), headers=headers)
            try:
                with urlopen(req, timeout=_EF_API_TIMEOUT) as resp:
                    data = json.loads(resp.read())
            # ValueError covers an invalid/missing URL scheme and json.JSONDecodeError;
            # http.client.HTTPException covers low-level protocol faults (BadStatusLine,
            # IncompleteRead) common with local/overloaded servers.
            except (HTTPError, URLError, OSError, http.client.HTTPException, ValueError) as e:
                raise EmbeddingAPIError(
                    f"Embedding API request to {self._url} failed: {e}. Check that the "
                    f"server is reachable and MEMPALACE_EMBEDDING_API_URL / embedding_api_url "
                    f"is correct."
                ) from e
            out.extend(self._vectors_from_response(data, len(batch)))
        return out

    def _vectors_from_response(self, data, n: int) -> list:
        """Validate one ``/v1/embeddings`` response and return L2-normed vectors.

        Guards every way a non-conformant server could corrupt the store
        silently: a missing/short ``data`` array, response ``index`` values
        that aren't the contiguous ``0..n-1`` batch positions (sorting then
        zipping positionally would otherwise misalign vectors with texts), and
        malformed / ragged / base64 embedding payloads. All failures raise
        :class:`EmbeddingAPIError` naming the endpoint rather than a cryptic
        numpy error — a silent wrong result would break the 100%-recall promise.
        """

View on GitHub (pinned to 06cb6987f0)

Solutions

  1. Verify the server is up: curl -s http://host:port/v1/embeddings -d '{"model":"x","input":["hi"]}' -H 'Content-Type: application/json'
  2. 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://)
  3. If the server was slow to start (first model load), wait for it to finish loading and retry
  4. Disable proxying for localhost if a corporate proxy is set: export NO_PROXY=localhost,127.0.0.1
  5. For IncompleteRead/BadStatusLine under load, reduce concurrent mempalace operations or raise the server's worker capacity

Example fix

# before
export MEMPALACE_EMBEDDING_API_URL=127.0.0.1:1234  # missing scheme -> ValueError path
# after
export MEMPALACE_EMBEDDING_API_URL=http://127.0.0.1:1234

# retry wrapper
from mempalace.embedding import EmbeddingAPIError
try:
    vecs = ef(texts)
except EmbeddingAPIError as e:
    if 'failed' in str(e):
        time.sleep(2); vecs = ef(texts)  # server still warming up
Defensive patterns

Strategy: retry

Validate before calling

import socket
from urllib.parse import urlparse

def endpoint_reachable(url: str, timeout: float = 2.0) -> bool:
    u = urlparse(url)
    if u.scheme not in ("http", "https") or not u.hostname:
        return False
    with socket.socket() as s:
        s.settimeout(timeout)
        return s.connect_ex((u.hostname, u.port or (443 if u.scheme == 'https' else 80))) == 0

Try / catch

from mempalace.embedding import EmbeddingAPIError
import time

for attempt in range(3):
    try:
        vecs = ef(texts)
        break
    except EmbeddingAPIError as e:
        if attempt == 2 or "non-object" in str(e) or "malformed" in str(e):
            raise  # only retry transport faults, not schema errors
        time.sleep(2 ** attempt)  # server may still be loading its model

Prevention

When it happens

Trigger: 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.

Common situations: 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://.

Related errors


AI-assisted analysis of MemPalace/mempalace@06cb6987f0 (2026-08-15). Data as JSON: /api/errors/5906bebd953bbae2. Report an issue: GitHub.