Skip to content

memorySearch provider: "local" fails with "Unknown memory embedding provider: local" but capability embedding path works #72875

@Amirofcodes

Description

@Amirofcodes

Summary

memorySearch.provider = "local" appears to be a supported memory embedding configuration, but the memory CLI/runtime path can fail with:

Unknown memory embedding provider: local

The same local provider works through the embedding capability CLI, so this may be a provider-registration difference between the capability path and the memory runtime path.

Impact

This prevents enabling local memory search with a local GGUF embedding model. In my setup, disabling agents.defaults.memorySearch.enabled restores normal gateway/CLI health, but leaves semantic memory search disabled.

Environment where reproduced

  • OpenClaw package version: 2026.4.23
  • Node: 22.22.0
  • Install method: global npm install
  • Memory store: SQLite-backed memory search with vector enabled
  • Local embedding model: GGUF embedding model

I also inspected latest source main before filing this:

  • Repository: openclaw/openclaw
  • main commit inspected: 3120401f
  • package.json version on main: 2026.4.26

The latest source still appears to have the same registration split described below, but I have not yet run a full source build/reproduction on main.

Relevant sanitized config

{
  "agents": {
    "defaults": {
      "memorySearch": {
        "enabled": true,
        "sources": ["memory"],
        "provider": "local",
        "fallback": "none",
        "local": {
          "modelPath": "/path/to/model.gguf",
          "modelCacheDir": "/path/to/model-cache"
        },
        "store": {
          "driver": "sqlite",
          "path": "/path/to/memory/{agentId}.sqlite",
          "vector": {
            "enabled": true
          }
        }
      }
    }
  }
}

Why local appears supported

I am not assuming this only from behavior; here is the source/schema evidence I found.

On latest source main (3120401f, package version 2026.4.26):

The line references below are from my local checkout of main at commit 3120401f; they may shift on newer commits.

  1. The generated config schema lists local as a memory search provider:
src/config/schema.base.generated.ts:4275-4279
provider: {
  type: "string",
  title: "Memory Search Provider",
  description:
    'Selects the embedding backend used to build/query memory vectors: "openai", "gemini", "voyage", "mistral", "bedrock", "lmstudio", "ollama", or "local". Keep your most reliable provider here and configure fallback for resilience.',
}
  1. The schema says local.modelPath accepts a GGUF path or hf: URI:
src/config/schema.base.generated.ts:4457-4464
local: {
  type: "object",
  properties: {
    modelPath: {
      type: "string",
      title: "Local Embedding Model Path",
      description:
        "Specifies the local embedding model source for local memory search, such as a GGUF file path or `hf:` URI. Use this only when provider is `local`, and verify model compatibility before large index rebuilds.",
    },
  1. The memory-core source defines a built-in local adapter:
extensions/memory-core/src/memory/provider-adapters.ts:87-115
const localAdapter: MemoryEmbeddingProviderAdapter = {
  id: "local",
  defaultModel: DEFAULT_LOCAL_MODEL,
  transport: "local",
  autoSelectPriority: 10,
  ...
};

export const builtinMemoryEmbeddingProviderAdapters = [localAdapter] as const;
  1. The memory-core source exposes a built-in provider registration helper:
extensions/memory-core/src/memory/provider-adapters.ts:125-135
export function registerBuiltInMemoryEmbeddingProviders(register: {
  registerMemoryEmbeddingProvider: (adapter: MemoryEmbeddingProviderAdapter) => void;
}): void {
  ...
  register.registerMemoryEmbeddingProvider(adapter);
}

Actual behavior

With memory search enabled and provider = "local", this command triggers the failure:

openclaw memory status --deep

The memory runtime/CLI initialization fails with:

Unknown memory embedding provider: local

Sanitized stack shape from the installed 2026.4.23 package:

Error: Unknown memory embedding provider: local
    at getAdapter (.../dist/manager-*.js)
    at createEmbeddingProvider (.../dist/manager-*.js)
    at MemoryIndexManager.loadProviderResult (.../dist/manager-*.js)
    at MemoryIndexManager.ensureProviderInitialized (.../dist/manager-*.js)
    at MemoryIndexManager.probeVectorAvailability (.../dist/manager-*.js)
    at openclaw memory status --deep

Disabling memory search avoids the error:

{
  "agents": {
    "defaults": {
      "memorySearch": {
        "enabled": false
      }
    }
  }
}

Expected behavior

If local is a supported memory embedding provider and a valid local model path is configured, memory CLI/runtime commands that initialize memory search should not throw Unknown memory embedding provider: local.

For example:

openclaw config validate
openclaw memory status --deep

should either report local embedding readiness or a local runtime/model setup error, not an unknown provider error.

Evidence that local embeddings work through another path

The local provider is visible and usable through the capability embedding path in the installed package:

openclaw capability embedding providers --json

Sanitized result shape:

[
  {
    "available": true,
    "id": "local",
    "transport": "local",
    "autoSelectPriority": 10
  }
]

And:

openclaw capability embedding create --provider local --text "ping" --json

Sanitized result shape:

{
  "ok": true,
  "provider": "local",
  "dimensions": 768
}

Suspected cause

The capability embedding CLI path explicitly registers built-in memory embedding providers before creating embeddings:

src/cli/capability-cli.ts:1356
ensureMemoryEmbeddingProvidersRegistered();

src/cli/capability-cli.ts:1388-1394
function ensureMemoryEmbeddingProvidersRegistered(): void {
  if (listMemoryEmbeddingProviders().length > 0) {
    return;
  }
  registerBuiltInMemoryEmbeddingProviders({
    registerMemoryEmbeddingProvider,
  });
}

The memory manager path appears to create the embedding provider without an equivalent built-in registration step:

extensions/memory-core/src/memory/manager.ts:156-165
private static async loadProviderResult(...) {
  return await createEmbeddingProvider({
    config: params.cfg,
    agentDir: resolveAgentDir(params.cfg, params.agentId),
    ...resolveMemoryPrimaryProviderRequest({ settings: params.settings }),
  });
}

The latest source main manager runtime entrypoint is only a re-export:

extensions/memory-core/manager-runtime.ts:1
export { closeAllMemoryIndexManagers, MemoryIndexManager } from "./src/memory/manager-runtime.js";

The memory-core plugin entry does register built-ins during plugin registration:

extensions/memory-core/index.ts:30
registerBuiltInMemoryEmbeddingProviders(api);

But the memory CLI/runtime path that dynamically loads the memory manager seems able to run without that plugin registration having populated the memory embedding provider registry.

Diagnostic-only local proof

As a diagnostic experiment only, registering built-in memory embedding providers before creating/using MemoryIndexManager allowed the memory manager to resolve provider: "local" in an isolated test.

I understand installed dist files are built output and are not the correct PR target. I am mentioning this only to identify the suspected missing registration step, not as the proposed source patch.

Suggested direction

Please confirm the intended architecture for memory embedding provider registration in CLI/runtime paths.

If the analysis is correct, a source-level fix could register built-in memory embedding providers before memory manager/provider initialization in the memory CLI/runtime path, or centralize registration so capability and memory runtime paths behave consistently.

A regression test would be useful for:

  • memory search enabled,
  • provider: "local",
  • local/built-in provider registry available,
  • expected: no Unknown memory embedding provider: local when memory status/provider initialization runs.

Notes

  • If this has already been fixed after 2026.4.23, which release contains the fix?
  • If main expects a different initialization path, guidance on the correct source patch location would be appreciated.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions