MemPalace/mempalace · error · ValueError
LLM_ENDPOINT must use http:// or https:// (got scheme {schem
Error message
LLM_ENDPOINT must use http:// or https:// (got scheme {scheme!r}) What it means
Raised by the ClosetLLM constructor when LLM_ENDPOINT (or the --endpoint argument) has a URL scheme other than http or https. This is a deliberate privacy-by-architecture guard: the HTTP client could otherwise be pointed at file:// (or other schemes some clients honor), letting a misconfigured or injected endpoint read and exfiltrate local files. Only plain HTTP endpoints — local (Ollama, vLLM, LM Studio) or explicit BYOK cloud — are permitted.
Source
Thrown at mempalace/closet_llm.py:112
class LLMConfig:
"""Resolved LLM connection config. CLI flags > env vars."""
def __init__(
self,
endpoint: Optional[str] = None,
key: Optional[str] = None,
model: Optional[str] = None,
):
self.endpoint = (endpoint or os.environ.get("LLM_ENDPOINT", "")).rstrip("/")
self.key = key or os.environ.get("LLM_KEY", "")
self.model = model or os.environ.get("LLM_MODEL", "")
if self.endpoint:
# Privacy-by-architecture: reject file:// and other non-HTTP schemes
# so a misconfigured endpoint cannot exfiltrate local files.
scheme = urllib.parse.urlparse(self.endpoint).scheme.lower()
if scheme not in ("http", "https"):
raise ValueError(
f"LLM_ENDPOINT must use http:// or https:// (got scheme {scheme!r})"
)
def missing(self) -> list:
missing = []
if not self.endpoint:
missing.append("LLM_ENDPOINT (or --endpoint)")
if not self.model:
missing.append("LLM_MODEL (or --model)")
# key is optional — local inference servers (Ollama, vLLM) often don't require one
return missing
def _call_llm(cfg: LLMConfig, source_file: str, wing: str, room: str, content: str):
"""Single LLM call via OpenAI-compatible /chat/completions.
Returns (parsed_json_dict_or_None, usage_dict_or_None).
"""View on GitHub (pinned to 06cb6987f0)
Solutions
- Set the endpoint with an explicit scheme: LLM_ENDPOINT=http://localhost:11434 for Ollama, https://... for cloud BYOK
- If you intended a unix socket, point at the HTTP listen address of the local runtime instead
- Audit the environment/hook config that injects LLM_ENDPOINT for a stale file:// value
Example fix
# before export LLM_ENDPOINT="localhost:11434" # scheme '' -> ValueError # after export LLM_ENDPOINT="http://localhost:11434"
Defensive patterns
Strategy: validation
Validate before calling
from urllib.parse import urlparse
endpoint = os.environ.get("LLM_ENDPOINT", "")
if endpoint and urlparse(endpoint).scheme.lower() not in ("http", "https"):
endpoint = "http://" + endpoint # fix missing scheme for localhost runtimes
os.environ["LLM_ENDPOINT"] = endpoint Type guard
def is_http_endpoint(url: str) -> bool:
return urlparse(url).scheme.lower() in ("http", "https") Try / catch
try:
llm = ClosetLLM()
except ValueError as exc:
if "LLM_ENDPOINT" in str(exc):
raise SystemExit(f"fix LLM_ENDPOINT: {exc} (use http://host:port)") from None
raise Prevention
- Always write local endpoints with the scheme: http://localhost:11434
- Validate LLM_ENDPOINT in setup scripts before first use
- Treat a non-HTTP scheme as a red flag for exfiltration misconfiguration, not just a typo
When it happens
Trigger: Constructing the LLM client with endpoint='file:///etc/passwd', LLM_ENDPOINT='unix:///run/ollama.sock', an empty-scheme value like 'localhost:11434' (parsed scheme becomes ''), or any gopher/ftp/file URL. Note the check fires only when the endpoint is non-empty.
Common situations: Forgetting the http:// prefix (LLM_ENDPOINT=localhost:11434 — urlparse yields scheme ''); trying to use a unix socket URL; a .env or hook config carrying a file:// path copied from another tool; typo like http:/ (single slash still parses as http, but htp:// does not).
Related errors
- {field_name} contains invalid path characters
- {field_name} contains null bytes
- HTTP {e.code} from {url}: {detail or e.reason}
- openai-compat provider requires --llm-endpoint
- Anthropic provider requires ANTHROPIC_API_KEY env or --llm-a
AI-assisted analysis of MemPalace/mempalace@06cb6987f0 (2026-08-15).
Data as JSON: /api/errors/8fb5663add098213.
Report an issue: GitHub.