Mintplex-Labs/anything-llm · error · Error

LMStudio service could not be reached. Is LMStudio running?

Error message

LMStudio service could not be reached. Is LMStudio running?

What it means

Thrown at the top of LMStudioEmbedder.embedChunks when the private #isAlive() check fails. #isAlive() calls GET /models on the LM Studio server and requires a non-empty model list, so this error fires both when the server is unreachable (connection refused, logged then false) AND when LM Studio is running but has zero models loaded.

Solutions

  1. Open LM Studio and start the local server; confirm it prints the same URL as EMBEDDING_BASE_PATH
  2. Load at least one model in LM Studio — the health check requires the /models list to be non-empty
  3. curl the /models endpoint yourself (curl http://localhost:1234/v1/models) to distinguish 'unreachable' from 'no models'
  4. If the port differs from 1234, update EMBEDDING_BASE_PATH accordingly
  5. Retry the embed once the server reports at least one loaded model

Example fix

# LM Studio not serving any model -> health check fails even though app is running:
# before
lms load --verbose   # (or UI: nothing loaded, server on)

# after
lms load nomic-embed-text-v1.5 --verbose
curl http://localhost:1234/v1/models   # must return non-empty data[]
Defensive patterns

Strategy: try-catch

Validate before calling

// Mirror the internal #isAlive() contract: reachable AND at least one model loaded
const { OpenAI } = require("openai");
async function lmStudioAlive(basePath) {
  const openai = new OpenAI({ baseURL: basePath, apiKey: process.env.LMSTUDIO_AUTH_TOKEN ?? null });
  try {
    const res = await openai.models.list();
    return (res?.data?.length ?? 0) > 0;
  } catch (e) {
    console.error("LMStudio unreachable:", e.message);
    return false;
  }
}
if (!(await lmStudioAlive(process.env.EMBEDDING_BASE_PATH))) {
  // show 'start LM Studio server and load a model' instead of attempting the embed
}

Try / catch

try {
  const vectors = await embedder.embedTextInput(text);
} catch (e) {
  if (e.message.includes("LMStudio service could not be reached")) {
    // two distinct causes: server down (connection refused in logs) or zero models loaded
    // start the LM Studio server AND load a model, then retry — the state can change, so retry is valid
  } else throw e;
}

Prevention

When it happens

Trigger: LM Studio app open but the local server not started (Developer tab toggle off); server on a different port than EMBEDDING_BASE_PATH; server running with no model loaded (fresh headless launch without --load), so models.list() returns [] and data.length > 0 is false; firewall/loopback issues; LM Studio crashed between document uploads.

Common situations: 'Is LMStudio running?' during first-run setups where the UI is open but the server was never started; headless/CLI LM Studio instances with no default model; embedding after a machine reboot where LM Studio did not auto-start its server.

Understand the failure class

Background: ECONNREFUSED and "connection refused" / "could not connect to server" errors: what they mean and how to fix them — this error's family across 44 libraries.

Related errors


AI-assisted analysis of Mintplex-Labs/anything-llm@3aec848f28 (2026-08-18). Data as JSON: /api/errors/b3fa7cab01aa4fdc. Report an issue: GitHub.

Appendix: source

Thrown at server/utils/EmbeddingEngines/lmstudio/index.js:51

    return await this.lmstudio.models
      .list()
      .then((res) => res?.data?.length > 0)
      .catch((e) => {
        this.log(e.message);
        return false;
      });
  }

  async embedTextInput(textInput) {
    const result = await this.embedChunks(
      Array.isArray(textInput) ? textInput : [textInput]
    );
    return result?.[0] || [];
  }

  async embedChunks(textChunks = []) {
    if (!(await this.#isAlive()))
      throw new Error(
        `LMStudio service could not be reached. Is LMStudio running?`
      );

    this.log(
      `Embedding ${textChunks.length} chunks of text with ${this.model}.`
    );

    // LMStudio will drop all queued requests now? So if there are many going on
    // we need to do them sequentially or else only the first resolves and the others
    // get dropped or go unanswered >:(
    let results = [];
    let hasError = false;
    for (const [idx, chunk] of textChunks.entries()) {
      if (hasError) break;
      results.push(
        await this.lmstudio.embeddings
          .create({
            model: this.model,

View on GitHub (pinned to 3aec848f28)