[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:
historyDbPath provided in user config is effectively ignored in open-source mode.
- 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:
relative to the process current working directory.
If the process is started with cwd=/, SQLite attempts to open:
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:
the vector store tries to create:
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
- Start a Node.js process in open-source mode with current working directory set to
/.
- 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
};
- Do not explicitly set
historyStore.
- 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()
- Start a Node.js process with
cwd=/.
- Use the OSS in-memory vector store path.
- Initialize memory or perform an operation that triggers vector store setup.
Observed behavior
The library attempts to create:
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:
or another platform-appropriate app data path.
Current workaround
The current workaround on my side is:
- Patch config initialization so that it explicitly sets:
config.historyStore = {
provider: "sqlite",
config: {
historyDbPath: dbPath
}
};
- 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.
[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 themem0ainpm package:historyDbPathprovided in user config is effectively ignored in open-source mode.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
mem0ainpm packagev1.1.x@mem0/openclaw-mem0v0.3.0v25.8.026.3(Apple Silicon)cwd=/Bug 1:
historyDbPathconfig is ignoredProblem
When using open-source mode with
historyDbPathset to an absolute path, the library still initializes the SQLite history DB using the default relative pathmemory.db.Why this happens
From the built open-source bundle (
dist/oss/index.mjs), the flow appears to be:1)
ConfigManager.mergeConfig()populateshistoryStorefrom defaultsAround line
~3723,historyStoreis always merged from defaults:The default appears to include:
If the user only sets top-level
historyDbPathand does not explicitly sethistoryStore, thenhistoryStore.config.historyDbPathremains the default relative value"memory.db".2)
Memory._init()always prefersthis.config.historyStoreAround line
~4488,Memory._init()appears to usethis.config.historyStorewhenever it is truthy.Because
historyStoreis always populated by defaults, the initialization never falls through to any branch that would read the top-levelthis.config.historyDbPath.3)
HistoryManagerFactory.create()receives the default pathAs a result,
HistoryManagerFactory.create()receives:instead of the absolute path the user supplied via top-level
historyDbPath.Actual result
The SQLite history DB is created as:
relative to the process current working directory.
If the process is started with
cwd=/, SQLite attempts to open:which fails with an error like:
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.historyDbPathshould be propagated into:before history initialization occurs.
Bug 2: in-memory vector store uses
process.cwd()for DB pathProblem
In
src/oss/src/vector_stores/memory.ts, the SQLite path for the vector store is hardcoded to the process working directory:Actual result
When the process is running with:
the vector store tries to create:
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:
~/.mem0/vector_store.dbWhy 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:
cwdmay be/cwdmay not be writablecwdmay vary depending on how the process is startedThe 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:
historyDbPathignored/.mem0aiwith a top-level absolutehistoryDbPath, for example:historyStore.Observed behavior
The library still attempts to use relative
memory.dbfrom defaulthistoryStore.config.historyDbPath, effectively resolving againstcwd.In a non-writable
cwd, this fails with:Repro B: vector store DB path anchored to
process.cwd()cwd=/.Observed behavior
The library attempts to create:
and fails if
/is not writable.Minimal reasoning behind the fix
Suggested fix for Bug 1
In
ConfigManager.mergeConfig(), ifuserConfig.historyDbPathis set, propagate it into the merged history store config.Conceptually something like:
This ensures top-level
historyDbPathis not lost when defaulthistoryStoreis 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:or another platform-appropriate app data path.
Current workaround
The current workaround on my side is:
dist/oss/index.mjs/ vector store handling sovector_store.dbuses an absolute writable path instead ofprocess.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
mem0aiin environments such as: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
historyDbPathshould reliably control the history SQLite path in OSS mode.process.cwd()unless explicitly requested.Nice-to-have
It would also help if path resolution behavior were documented clearly for OSS mode, including:
historyDbPathandhistoryStore.config.historyDbPathprocess.cwd()or another base directoryThanks — happy to help test a fix if useful.