Skip to content

[Bug] historyDbPath ignored in open-source mode — SQLite always uses relative "memory.db" + vector_store.db uses process.cwd() #4290

Description

@mudrii

[Bug] historyDbPath ignored in open-source mode — SQLite always uses relative "memory.db" + vector_store.db uses process.cwd()

Summary

There appear to be two related path-handling issues in the open-source (oss) flow of the mem0ai npm package:

  1. historyDbPath provided in user config is effectively ignored in open-source mode.
  2. The in-memory vector store hardcodes its SQLite DB path to path.join(process.cwd(), "vector_store.db").

Together, these cause failures when the process runs with a non-writable current working directory (for example / under LaunchAgent/systemd-style service execution).

Environment

  • Package: mem0ai npm package v1.1.x
  • Integration path: via @mem0/openclaw-mem0 v0.3.0
  • Runtime: Node.js v25.8.0
  • OS: macOS 26.3 (Apple Silicon)
  • Execution mode: LaunchAgent / service-style process with cwd=/
  • Embeddings / OSS mode: Ollama embeddings in open-source mode

Bug 1: historyDbPath config is ignored

Problem

When using open-source mode with historyDbPath set to an absolute path, the library still initializes the SQLite history DB using the default relative path memory.db.

Why this happens

From the built open-source bundle (dist/oss/index.mjs), the flow appears to be:

1) ConfigManager.mergeConfig() populates historyStore from defaults

Around line ~3723, historyStore is always merged from defaults:

historyStore: {
  ...DEFAULT_MEMORY_CONFIG.historyStore,
  ...userConfig.historyStore
}

The default appears to include:

historyStore: {
  provider: "sqlite",
  config: { historyDbPath: "memory.db" }
}

If the user only sets top-level historyDbPath and does not explicitly set historyStore, then historyStore.config.historyDbPath remains the default relative value "memory.db".

2) Memory._init() always prefers this.config.historyStore

Around line ~4488, Memory._init() appears to use this.config.historyStore whenever it is truthy.

Because historyStore is always populated by defaults, the initialization never falls through to any branch that would read the top-level this.config.historyDbPath.

3) HistoryManagerFactory.create() receives the default path

As a result, HistoryManagerFactory.create() receives:

historyStore.config.historyDbPath === "memory.db"

instead of the absolute path the user supplied via top-level historyDbPath.

Actual result

The SQLite history DB is created as:

memory.db

relative to the process current working directory.

If the process is started with cwd=/, SQLite attempts to open:

/memory.db

which fails with an error like:

SqliteError: unable to open database file

Expected result

If the user sets top-level historyDbPath, that value should override the default SQLite history DB path used in open-source mode.

At minimum, userConfig.historyDbPath should be propagated into:

historyStore.config.historyDbPath

before history initialization occurs.


Bug 2: in-memory vector store uses process.cwd() for DB path

Problem

In src/oss/src/vector_stores/memory.ts, the SQLite path for the vector store is hardcoded to the process working directory:

this.dbPath = path.join(process.cwd(), "vector_store.db");

Actual result

When the process is running with:

cwd=/

the vector store tries to create:

/vector_store.db

which fails if the directory is not writable.

Expected result

The vector store DB path should be configurable, or at least default to a user-writable location instead of process.cwd().

Examples of safer defaults:

  • a config-provided absolute path
  • a directory under the user home, e.g. ~/.mem0/vector_store.db
  • a platform-appropriate application data directory

Why these bugs are related

Both issues assume that relative SQLite paths anchored to process.cwd() are acceptable defaults.

That assumption breaks in service environments, containers, daemons, LaunchAgents, and systemd units where:

  • cwd may be /
  • cwd may not be writable
  • cwd may vary depending on how the process is started

The result is non-portable behavior and confusing path resolution failures even when the caller provides an absolute DB path for history.


Steps to reproduce

Repro A: historyDbPath ignored

  1. Start a Node.js process in open-source mode with current working directory set to /.
  2. Configure mem0ai with a top-level absolute historyDbPath, for example:
const config = {
  historyDbPath: "/Users/youruser/.mem0/history.db",
  // other OSS config, e.g. Ollama embeddings
};
  1. Do not explicitly set historyStore.
  2. Initialize memory and perform an operation that creates or accesses the history store.

Observed behavior

The library still attempts to use relative memory.db from default historyStore.config.historyDbPath, effectively resolving against cwd.

In a non-writable cwd, this fails with:

SqliteError: unable to open database file

Repro B: vector store DB path anchored to process.cwd()

  1. Start a Node.js process with cwd=/.
  2. Use the OSS in-memory vector store path.
  3. Initialize memory or perform an operation that triggers vector store setup.

Observed behavior

The library attempts to create:

/vector_store.db

and fails if / is not writable.


Minimal reasoning behind the fix

Suggested fix for Bug 1

In ConfigManager.mergeConfig(), if userConfig.historyDbPath is set, propagate it into the merged history store config.

Conceptually something like:

const mergedHistoryStore = {
  ...DEFAULT_MEMORY_CONFIG.historyStore,
  ...userConfig.historyStore,
  config: {
    ...DEFAULT_MEMORY_CONFIG.historyStore?.config,
    ...userConfig.historyStore?.config,
    ...(userConfig.historyDbPath
      ? { historyDbPath: userConfig.historyDbPath }
      : {})
  }
};

This ensures top-level historyDbPath is not lost when default historyStore is materialized.

Suggested fix for Bug 2

Make the vector store DB path configurable through explicit config.

If no config is provided, default to a user-writable directory rather than process.cwd(), for example:

~/.mem0/vector_store.db

or another platform-appropriate app data path.


Current workaround

The current workaround on my side is:

  1. Patch config initialization so that it explicitly sets:
config.historyStore = {
  provider: "sqlite",
  config: {
    historyDbPath: dbPath
  }
};
  1. Patch dist/oss/index.mjs / vector store handling so vector_store.db uses an absolute writable path instead of process.cwd().

This works around the immediate failure, but callers should not need to patch internals for a user-specified DB path to be respected.


Impact

This affects users running mem0ai in environments such as:

  • LaunchAgent / launchd services
  • systemd services
  • background daemons
  • containers
  • supervisors that set cwd=/

It is especially surprising because the user may already be providing an explicit absolute historyDbPath, but the library silently falls back to the default relative path anyway.


Expected outcome

  • Top-level historyDbPath should reliably control the history SQLite path in OSS mode.
  • Vector store SQLite path should not depend on process.cwd() unless explicitly requested.
  • Service / daemon execution should work without patching internals.

Nice-to-have

It would also help if path resolution behavior were documented clearly for OSS mode, including:

  • precedence between historyDbPath and historyStore.config.historyDbPath
  • where vector store DB files are created by default
  • whether relative paths are resolved from process.cwd() or another base directory

Thanks — happy to help test a fix if useful.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P1-highBlocks significant use case, high demandsdk-typescriptTypeScript/Node.js SDK specific

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions