When something breaks
The errors this install produces, and what each one means.
Find the message you are looking at, not the step you are on. Each entry shows the symptom first, says in plain language what it means, and ends with the command or the action that clears it.
Python and Docker
Everything else depends on these two answering. If the very first check in the guide gave you nothing back, start here.
The shell says it does not know what python is
python : The term 'python' is not recognized as the name of a cmdlet, function, script file, or operable program. At line:1 char:1 or, on macOS and Linux: command not found: python
Two different things produce this. Either Python is not installed, or it is installed and the shell was never told where to find it. On Windows the installer only puts Python on your PATH when you tick the box during installation, and there is a second launcher called py that often works when python does not. On macOS and Linux the command is python3, and plain python may not exist at all.
Find out which case you are in.
py --versionpython3 --versionpython3 --versionIf that prints a version, Python is on the machine and only the name was wrong. On macOS and Linux, use python3 everywhere this guide writes it and you are done. On Windows you can keep typing py, but I recommend reinstalling from python.org with the Add python.exe to PATH box ticked, because the rest of the guide, and every tool that shells out to Python, expects the plain name to work.
The version is below 3.11
Python 3.9.13Not an error message, but it stops you all the same. RE-call's floor is 3.11, and 3.12 to 3.14 are supported. An older interpreter will fail somewhere during the install with a syntax or dependency error that does not name the real cause.
Install a current version from python.org and check again before continuing. You do not have to remove the old one.
On Windows: Python works, but indexing a folder finds nothing
The Microsoft Store build is the usual cause
Python installed from the Microsoft Store runs inside a sandbox that rewrites file paths. Commands run, versions print, and then index reads a folder that is not the folder you meant. Install from python.org instead.
You can confirm which build you have. A path containing WindowsApps is the Store build.
python -c "import sys; print(sys.executable)"python3 -c "import sys; print(sys.executable)"python3 -c "import sys; print(sys.executable)"docker is not recognised, or the daemon will not answer
docker : The term 'docker' is not recognized as the name of a cmdlet, function, script file, or operable program. or Cannot connect to the Docker daemon. Is the docker daemon running?
The first message means Docker Desktop is not installed, or its command line tool was never added to your PATH. The second is the more common one, and it means something quite specific: the docker command exists and ran, but the engine behind it is not up. Installing Docker Desktop does not start it.
Open Docker Desktop from your applications and wait until it reports that the engine is running. Then check from the terminal.
docker psdocker psdocker psAn empty table with column headings is a success. It means the engine answered and has nothing running yet.
Database problems
Everything in step 1 of the install guide, and every later error that says the word "refused".
Port 5432 is already allocated
docker: Error response from daemon: driver failed programming external connectivity on endpoint recall-db: Bind for 0.0.0.0:5432 failed: port is already allocated
Something else on your machine is already listening on 5432, and it is almost always another PostgreSQL: one you installed years ago, one a different project started, or a second copy of this container. Docker will not put two things on one port.
You have two ways out. Stop whatever is holding the port, or leave it alone and give RE-call a different door into the same container.
docker run -d --name recall-db -e POSTGRES_USER=recall -e POSTGRES_PASSWORD=recall -e POSTGRES_DB=recall -p 5433:5432 pgvector/pgvector:pg18docker run -d --name recall-db -e POSTGRES_USER=recall -e POSTGRES_PASSWORD=recall -e POSTGRES_DB=recall -p 5433:5432 pgvector/pgvector:pg18docker run -d --name recall-db -e POSTGRES_USER=recall -e POSTGRES_PASSWORD=recall -e POSTGRES_DB=recall -p 5433:5432 pgvector/pgvector:pg18If you take the second route, one thing changes everywhere
Every connection string in the rest of the guide becomes postgresql://recall:recall@localhost:5433/recall, including the one inside .mcp.json. The 5433:5432 means "reach the container's 5432 by knocking on 5433 here", so only the number you type changes.
The container name is already in use
docker: Error response from daemon: Conflict. The container name "/recall-db" is already in use You have to remove (or rename) that container to be able to reuse that name.
An earlier attempt created a container called recall-db. It may be stopped, it may be broken, but the name is taken. Remove it and run the command again.
docker rm -f recall-dbdocker rm -f recall-dbdocker rm -f recall-dbIf the old container was working and only the name collided, check first whether you simply want to start it again rather than throw it away. The next entry covers that.
Connection refused
connection to server at "localhost" (::1), port 5432 failed: Connection refused Is the server running on that host and accepting TCP/IP connections?
Nothing is listening. The database is not running, which after a reboot is the ordinary state of affairs: a stopped container stays stopped until you start it. This is the error behind most failures in schema, index and search, so if you see it there, you are in the right section.
docker ps lists what is running. docker ps -a also lists what has stopped, which is where a container you made yesterday will be hiding.
docker ps -adocker start recall-db
docker ps -adocker start recall-db
docker ps -adocker start recall-db
You should see
CONTAINER ID IMAGE STATUS PORTS NAMES a1b2c3d4e5f6 pgvector/pgvector:pg18 Up 2 seconds 0.0.0.0:5432->5432/tcp recall-db
If docker ps -a lists no container at all, there is nothing to start. Go back to step 1 of the install guide and run the docker run command.
Your memory disappeared between sessions
Searches that worked before now return nothing, or schema status reports that nothing is installed, and you know you indexed those files. What happened is that the container was removed and recreated. Its data lived inside it, so removing it removed your rows too.
Recreate the container with a named volume, so the data lives outside the container and survives being rebuilt.
docker run -d --name recall-db -e POSTGRES_USER=recall -e POSTGRES_PASSWORD=recall -e POSTGRES_DB=recall -p 5432:5432 -v recall_pgdata:/var/lib/postgresql pgvector/pgvector:pg18docker run -d --name recall-db -e POSTGRES_USER=recall -e POSTGRES_PASSWORD=recall -e POSTGRES_DB=recall -p 5432:5432 -v recall_pgdata:/var/lib/postgresql pgvector/pgvector:pg18docker run -d --name recall-db -e POSTGRES_USER=recall -e POSTGRES_PASSWORD=recall -e POSTGRES_DB=recall -p 5432:5432 -v recall_pgdata:/var/lib/postgresql pgvector/pgvector:pg18The data already lost is gone, so apply the schema and index your memory once more. From then on, rebuilding the container costs you nothing.
Install problems
Getting the package onto your machine, and getting the right one.
The install succeeded but the import fails
Traceback (most recent call last): ModuleNotFoundError: No module named 'recall.cli'
You installed recall rather than recall-rag. The name recall on PyPI belongs to an unrelated project, and it happens to occupy the same import name, so having both in one environment leaves Python finding the wrong one.
The package is recall-rag, the command is recall
You install recall-rag. In code and on the command line it is spelled recall. That asymmetry is the single most common install mistake.
python -m pip uninstall recallpython -m pip install "recall-rag[fastembed]"
python3 -m pip uninstall recallpython3 -m pip install "recall-rag[fastembed]"
python3 -m pip uninstall recallpython3 -m pip install "recall-rag[fastembed]"
pip is not recognised
pip : The term 'pip' is not recognized as the name of a cmdlet, function, script file, or operable program. or command not found: pip
pip lives inside Python as a module. A standalone pip command is a convenience shim that is not always installed, and when several Pythons share a machine it is not always the shim for the interpreter you mean. Calling it through Python removes the guesswork, because the pip you reach is by definition the pip belonging to the Python you named.
That is why every install line in this guide is written python -m pip rather than pip. Use that form and this error cannot occur.
Permission denied while installing
ERROR: Could not install packages due to an OSError: [Errno 13] Permission denied Consider using the `--user` option or check the permissions.
You are installing into a Python that the operating system owns, and it is protecting itself. Running the install as an administrator would work and I do not recommend it: it mixes your project's dependencies into the interpreter your system relies on, and uninstalling later gets messy.
Create a virtual environment instead. It is a private copy of Python inside a folder, and it needs no special permissions.
python -m venv .venv.venv\Scripts\Activate.ps1python -m pip install "recall-rag[fastembed]"
python3 -m venv .venvsource .venv/bin/activatepython3 -m pip install "recall-rag[fastembed]"
python3 -m venv .venvsource .venv/bin/activatepython3 -m pip install "recall-rag[fastembed]"
You have to activate it in every new terminal
The activation line is the second one above. Open a fresh terminal and RE-call will look missing again until you run it. If a command that worked an hour ago suddenly reports that the module is not found, this is usually why.
Results are meaningless, or the wizard offers you nothing
If you installed plain recall-rag without the square brackets, you installed no embedding model at all. What you have instead is a placeholder that turns text into vectors by hashing it, which is useful for checking that the plumbing runs and useless for finding anything by meaning. The wizard will notice, and it will fall back to that placeholder rather than offering you a real choice.
The extra is what supplies the local model. Re-run the install with it.
python -m pip install "recall-rag[fastembed]"python3 -m pip install "recall-rag[fastembed]"python3 -m pip install "recall-rag[fastembed]"The first index sits there doing nothing
This one is not a fault
The first time you index anything, the local model has to be downloaded, roughly 130 MB. It happens once, during a command that otherwise finishes in a second, so it reads as a hang. Give it a few minutes on a normal connection. Every index after that starts immediately.
Schema problems
Creating the tables, and keeping their shape agreeing with your embedding model.
Connection refused during schema apply
The command never reached a database. This is not a schema fault at all, and applying it again will not help. Your container is not running: go to database problems, get docker ps showing recall-db, then run the schema apply line again unchanged.
vector type not found in the database
psycopg.ProgrammingError: vector type not found in the databaseThe wizard normally prepares the database for you, so this means it never got the chance: either it could not reach the database when you ran it, or this database was created outside the guide. It is running and reachable, but nothing has ever set it up: the vector extension that stores and compares embeddings is not installed, so the very first query that mentions a vector column fails. It usually appears from index or search, not from the step that was actually missed, which is what makes it confusing.
You do not need to install the extension by hand. Applying the schema does it for you, as the first thing it does. Re-running setup against a reachable database will also do it.
python -m recall.cli --migration-dsn postgresql://recall:recall@localhost:5432/recall schema --dim 384 applypython3 -m recall.cli --migration-dsn postgresql://recall:recall@localhost:5432/recall schema --dim 384 applypython3 -m recall.cli --migration-dsn postgresql://recall:recall@localhost:5432/recall schema --dim 384 applySchemaTooOld
recall.schema.SchemaTooOld: table 'chunks' needs schema migration(s) ['0001', '0002', ...]; run `recall schema apply`
Almost always this simply means the schema has never been applied to this database, and the wizard did not do it for you because it could not reach the database at the time. Apply it and the message goes away.
There is a second, rarer form of it, which names global generation migrations instead. RE-call's migrations are global: they set up the extension, the shared machinery, and the default chunks table that everything else is layered on. Until those have run once, the database has no foundation to build a custom table on, and any command that expects one refuses.
Never start with a custom table on a fresh database
Apply the global migrations against the default chunks table first, which is what the wizard does for you. Custom tables are an addition to a migrated database, not a substitute for migrating it.
python -m recall.cli --migration-dsn postgresql://recall:recall@localhost:5432/recall schema --dim 384 applypython -m recall.cli schema status
python3 -m recall.cli --migration-dsn postgresql://recall:recall@localhost:5432/recall schema --dim 384 applypython3 -m recall.cli schema status
python3 -m recall.cli --migration-dsn postgresql://recall:recall@localhost:5432/recall schema --dim 384 applypython3 -m recall.cli schema status
The table and the embedder disagree about width
An embedding model turns a piece of text into a list of numbers, and every model produces a list of one fixed length. The table's vector column is created at one specific width, and it will accept nothing else. If the two do not match, nothing can be written and nothing can be searched.
The local fastembed default produces 384 numbers, which is why the install guide builds the table with --dim 384. Here is what the others produce.
| Embedder | Vector width | Note |
|---|---|---|
| fastembed, default | 384 | What the install guide uses. Runs locally. |
| fastembed, base | 768 | Larger local model, larger download. |
| fastembed, large | 1024 | Larger still. |
| voyage | 1024 | Cloud embedder. Your text leaves the machine. |
| openai | 1536 | Cloud embedder. Your text leaves the machine. |
| hashing | 64 | Placeholder. No meaning, useful only for testing plumbing. |
Changing embedder therefore means rebuilding the table at the new width. There is no conversion: the numbers a different model produces are not a translation of the old ones, so the old rows have to be indexed again.
Why RE-call refuses rather than padding the vectors to fit
A vector is only meaningful against other vectors from the same model. Two lists of 384 numbers from different models are not comparable, and padding a 384 wide vector out to 768 would produce something a database will happily store and index, and that will return confident nonsense forever afterwards.
Refusing at the point of the mismatch is the cheap failure. The alternative is a corpus that looks healthy, answers every question, and is wrong in a way no error message will ever tell you about.
Setup wizard problems
The wizard asks its questions, checks your answers against the database, and refuses to write a configuration it knows will not work. Most of what looks like it going wrong is that check firing.
It keeps re-asking the embedder question
You choose an embedder, and instead of moving on the wizard asks again. It is not stuck. The embedder you picked produces vectors of one width, the table you built has another, and rather than writing a .env that fails on your first index it puts the question back to you along with the exact command that would reconcile the two. The message has this shape.
table 'chunks' uses vector(384), requested dimension is 768 fastembed base produces 768-dimension vectors. Either create a table with `recall schema --dim 768 apply`, or pick an embedder matching the table you have.
Both answers are legitimate, and which one is right depends on what you want.
- Keep the table. Choose the embedder whose width matches it. On a first install that is
fastembedat 384, and it is the answer the install guide expects. - Keep the embedder. Leave the wizard and rebuild the table at the new width, then start
setupagain. Note that the command the wizard prints is abbreviated:schema applyperforms DDL, so it needs--migration-dsnadded, exactly as the schema section shows. Anything already indexed has to be indexed again afterwards.
It exits saying no embedder matches this table
The same check, with nothing left to offer. Every embedder available in your environment produces a width the table cannot hold, so there is no answer you could give that would work, and the wizard stops rather than looping forever.
Two ways forward. Install the extra that provides an embedder of the right width, most often [fastembed] for a 384 wide table. Or rebuild the table at a width one of your installed embedders uses, with the schema --dim <n> apply command and the table in schema problems.
It picks the hashing placeholder by itself
This means the fastembed extra is missing
The wizard auto selects hashing only when nothing else can run. It is a placeholder that turns text into vectors without understanding any of it, so search will match on nothing you would recognise as meaning. Install "recall-rag[fastembed]" and run setup again.
Every database command refuses, and your .env looks odd
A .env file can be damaged, most often by a write that was interrupted partway and left a NUL byte in the middle of it. RE-call will not read a configuration it cannot trust, so every command that touches the database stops, which looks like a database fault and is not one.
There is an escape hatch, and setup is deliberately exempt from the guard so that you can always run it to write a clean file. Repairing is the better fix.
python -m recall.cli setuppython3 -m recall.cli setuppython3 -m recall.cli setupIf you need another command to run before you have repaired the file, override the guard for that one invocation.
$env:RECALL_IGNORE_BROKEN_DOTENV = "1"python -m recall.cli schema status
RECALL_IGNORE_BROKEN_DOTENV=1 python3 -m recall.cli schema statusRECALL_IGNORE_BROKEN_DOTENV=1 python3 -m recall.cli schema statusIt refuses the connection string as insecure
The credential this guide uses is recall:recall, which is a published username and password. That is fine against localhost, where nothing outside your machine can reach the port. Point the same credential at a host that is not local and RE-call refuses, because a database on the network with a password anyone can read in a setup guide is not a database, it is an open door.
The right fix is a real credential on the server, and the guard then stays out of your way. For setup specifically, pass the connection string on the command line.
python -m recall.cli --dsn postgresql://myuser:mypassword@db.example.com:5432/recall setuppython3 -m recall.cli --dsn postgresql://myuser:mypassword@db.example.com:5432/recall setuppython3 -m recall.cli --dsn postgresql://myuser:mypassword@db.example.com:5432/recall setupThe override exists, and I would not reach for it first
RECALL_ALLOW_INSECURE_DSN=1 switches the guard off. It is there for the cases where you genuinely know better, such as a throwaway container on a private network during a test.
Reaching for it on a real deployment converts a loud refusal into a silent risk, and the refusal is cheaper to fix now than the exposure is to discover later. Change the password instead.
Indexing and search
Getting your files into the database, and getting sensible answers back out. The first entry here is the one people hit most.
search ends in a Python traceback
Traceback (most recent call last): ... recall.trust_policy.TrustRefusal: INDEX_NOT_READY: refused in strict trust mode (tenant='default', generation=None, calibration_status='missing')
This is the most common failure in the whole install
Strict mode is the default, and in strict mode RE-call will not answer from a corpus whose confidence threshold has never been measured. It raises rather than quietly degrading, because a threshold nobody measured is not a threshold, and answering anyway would be exactly the behaviour the product exists to prevent. You have not measured one yet, so the very first search stops here.
The fix is the line from step 5 of the install guide. It says "I know this threshold is a placeholder, show me the results anyway", and everything you get back is stamped as uncertified so you cannot forget.
Add-Content .env "RECALL_TRUST_MODE=development"echo "RECALL_TRUST_MODE=development" >> .envecho "RECALL_TRUST_MODE=development" >> .envThat gets you moving today. The real answer is to measure a threshold on your own corpus, which replaces the placeholder with a number that means something and lets you drop development mode entirely. That is the calibration page, and it is worth doing once your memory holds material you care about being right.
If you added the line and the traceback persists, check you are running the command in the same folder as the .env file. The setting is read from the working directory.
Every result is flagged DEGRADED
[development] using an UNCERTIFIED demonstration threshold of 0.5. This is not a calibration: it is bound to no tenant, generation or corpus, and production refuses rather than assuming it. [DEGRADED:INDEX_NOT_READY] query='how many requests per minute can a client make?'
Not an error. It is the label doing its job.
In development mode the threshold in use is an uncertified demonstration value, bound to no corpus and no model. The flag is RE-call telling you so on every single result, so that nothing downstream can present these answers as measured ones. It disappears when you calibrate, and not before.
Nothing was indexed
indexed 0 chunks from 0 filesThe folder was found and read, and nothing in it matched. The default pattern is **/*.md, so a directory of .txt notes, .py source or .rst documents is skipped in silence: from index's point of view the folder is empty of things it was asked for.
Say what you want with --glob.
python -m recall.cli index notes/ --glob "**/*.txt"python3 -m recall.cli index notes/ --glob "**/*.txt"python3 -m recall.cli index notes/ --glob "**/*.txt"A re-index stops, saying it would remove most of your corpus
When you index a folder again, RE-call removes rows whose source files have gone. If a run is about to delete a large share of what is there, it stops instead. The usual cause is not a deletion at all: you pointed the command at the wrong folder, or a drive was not mounted, or you ran it from a different working directory, and the files look missing because the command cannot see them.
Check the path first. If the files really are gone and you meant it, the override is deliberate and explicit.
python -m recall.cli index memory/ --allow-prunepython3 -m recall.cli index memory/ --allow-prunepython3 -m recall.cli index memory/ --allow-pruneIndexing refuses under RECALL_ENV=production
Intended, not broken. In production RE-call does not build an index from whatever happens to be on a disk at the moment a command runs. It builds from an immutable manifest, so that what is being served is a thing somebody chose and can point to afterwards. Indexing a live folder would make the corpus depend on the state of a filesystem nobody recorded.
On your own machine, leave RECALL_ENV unset or set to development. If you meant to be in production, build the manifest rather than turning the guard off.
Searches run, but the answers are not useful
No error, no abstention, just results that are technically related and practically useless. This is almost never a configuration problem. It is what happens when the memory files are too broad: a long document covering six subjects produces chunks that are a bit about all of them and precisely about none, so nothing scores clearly against a specific question.
The fix is editorial rather than technical. One file, one subject, stated plainly, with the specifics in it. Your memory covers what makes a file findable and what to keep out of the corpus.
Claude Code problems
The MCP server is a separate process with its own configuration. Most problems here come from assuming it shares something with your terminal that it does not.
The server does not appear in Claude at all
You run /mcp, and there is no recall server listed. Three things to check, in this order.
- The
[mcp]extra is installed. The server component is not part of the base install. Run the install again with"recall-rag[fastembed,mcp]". .mcp.jsonis in the folder Claude Code was started from. Not your home directory, not the folder above. Claude reads it from the working directory it was launched in, so a file in the right project and the wrong folder is invisible.- Claude Code has been restarted. The file is read when the session starts. Editing it while Claude is running changes nothing until you quit and start again.
The server command fails to start
No module named recall_mcp.__main__; 'recall_mcp' is a package and cannot be directly executedThe module name in .mcp.json is one word short. recall_mcp is the package; the server inside it is recall_mcp.server, and that is what has to be run.
"args": ["-m", "recall_mcp.server"]
The server starts, but every search abstains or errors
The MCP server does not read your .env
Your terminal picks up .env from the working directory. The server is launched by Claude, not by your shell, and it does not read that file. Any setting you rely on has to be repeated inside the env block of .mcp.json, including the connection string and the trust mode. A missing RECALL_TRUST_MODE there is the usual reason searches work in the terminal and fail in Claude.
{
"mcpServers": {
"recall": {
"command": "python",
"args": ["-m", "recall_mcp.server"],
"env": {
"RECALL_SERVING_DSN": "postgresql://recall:recall@localhost:5432/recall",
"RECALL_TENANT": "default",
"RECALL_TRUST_MODE": "development"
}
}
}
}On macOS and Linux, the command name is wrong
The example above says "command": "python", which is the Windows spelling. On macOS and Linux change it to "python3", the same name you type in your own terminal. A wrong command name here shows up as a server that fails to start with no obvious explanation, because the failure happens inside Claude rather than in front of you.
Claude Desktop ignores your edit
Claude Desktop reads claude_desktop_config.json when it launches. Closing the window is not enough on either platform, because the application keeps running. Quit it fully and open it again, then check that the server is listed before you conclude the configuration is wrong.
Claude cannot see rows you indexed yourself
The table is fixed. The tenant is not.
The server always uses table chunks, and there is no setting that points it at another one. The tenant is different: it reads RECALL_TENANT from the env block of your configuration and falls back to default only when you have not set it.
So there are two distinct causes, with two different fixes.
- You indexed under another tenant, for example with
--tenant work. Do not re-index. Add"RECALL_TENANT": "work"to theenvblock in.mcp.jsonand restart Claude, and the existing rows become visible. - You indexed into a custom table, with
--table. Here re-indexing is the only route, because the server cannot be pointed at a different table. Index the material again without--tableso it lands inchunks.
If your problem is not on this page
Open an issue. Include the exact command you ran, the full message you got back, your operating system, and the output of python -m recall.cli schema status. Those four things are usually enough to identify the cause without a conversation.
github.com/GiulioDER/RE-call/issues
- Back to the install Seven steps from nothing to a memory that answers you, each with something you can check. โ
- Measure your threshold The long term answer to the trust refusal, and the way out of development mode. โ
- Fill your memory What makes a memory file findable, and why broad documents return unusable answers. โ