What to do when you change embedding models and the stored vectors no longer match.
The brain turns every chunk of your pages into an embedding: a list of numbers that lets search find text by meaning. Every embedding model produces lists of a fixed length, called its dimensions, and the database column that stores them is created at exactly that length.
If you switch to a model with a different number of dimensions, the stored vectors no longer fit. This guide shows how to spot the mismatch, how to rebuild the column on the local engine (PGLite) or on Postgres, and how to re-embed your pages afterwards.
nexusbrain init, on either the local engine (PGLite) or Postgres.provider:model form (for example openai:text-embedding-3-large) and its dimension count.nexusbrain serve stopped, because only one process can open the local database at a time.Two settings in the config file ~/.nexusbrain/config.json decide the embedding size: embedding_model and embedding_dimensions. They can be overridden for one shell with the NEXUS_BRAIN_EMBEDDING_MODEL and NEXUS_BRAIN_EMBEDDING_DIMENSIONS environment variables.
When the brain is created, nexusbrain init sizes the content_chunks.embedding column as vector(N) using those settings. Changing the settings later does not resize the column. That is why a model change needs one of the procedures below.
You cannot change these two keys with nexusbrain config set. That command writes to the database, which the embed pipeline never reads for these keys, so it refuses and prints the correct recipe instead.
| Engine | How the column is rebuilt | Command |
|---|---|---|
| Local (PGLite) | Wipe and re-create the brain, then re-import from your brain repo | nexusbrain reinit-pglite |
| Postgres | Rebuild the column in place, keeping your pages | nexusbrain migrate embeddings or the SQL recipe |
Every path in this guide deletes all stored embeddings. Search falls back to keyword matching until the re-embed finishes, and going back to the old model means paying for a second full re-embed.
Do not add --fast. That flag skips every database check, including the embedding checks.
nexusbrain doctorYou should seeA list of checks, each marked [OK], [WARN] or [FAIL]. On a healthy brain, embedding_width_consistency reads Schema width (1536d) matches gateway embedding_dimensions with your own number.
A mismatch shows as [WARN] embedding_width_consistency: Schema width mismatch: content_chunks.embedding is vector(1536) but gateway resolved embedding_dimensions = 1280. followed by Embedding dimension mismatch detected. and a copyable recipe for your engine.
If your provider key works, the embedding_provider check may also report DB dimension mismatch: column is vector(1536) but provider returns 1280-dim.
You should seeYou know the current column size (the first number) and the size the new model needs (the second number).
Re-embedding sends every chunk in your brain to the new provider, so the cost grows with the size of your brain. For Postgres brains the brain itself warns that this can take hours and cost $1 to $100 in API calls.
The migrate embeddings command has a planning mode that counts the work and prices it without changing anything. Use your new model and size.
nexusbrain migrate embeddings --to openai:text-embedding-3-large --dim 1536 --dry-runYou should seeAn Embedding migration plan block with From:, To:, Chunks to re-embed: and Estimated cost:. If the model has no pricing entry, it says the estimate is unknown and asks you to check the provider pricing.
| Where you see it | Message |
|---|---|
nexusbrain doctor | Embedding dimension mismatch detected. |
nexusbrain embed or nexusbrain init | Refusing to silently re-template existing brain. |
| Both | Existing column: vector(N) and Requested: vector(M) |
Set a budget before you start. See Spend controls for how caps and cost gates work.
The local engine stores vectors with pgvector compiled to WebAssembly, which cannot change a vector column type in place. The supported path is to move the old brain aside, create a new one at the new size, and import your brain repo again. nexusbrain reinit-pglite does all three.
nexusbrain serve if it is running.Close the terminal running it, or stop the agent app that launched it.
You should seeNo nexusbrain serve process is left running.
Each flag defaults to the value in ~/.nexusbrain/config.json when you leave it out. Environment variable overrides are ignored on purpose, so a temporary shell setting cannot change the rebuild target.
nexusbrain reinit-pglite --embedding-model zeroentropyai:zembed-1 --embedding-dimensions 1280You should seeA plan listing Active brain:, Backup destination:, New embedding model:, New dimensions: and Re-sync after init:, then the prompt Wipe and reinit? (y/N):.
y and press Enter.You should seeBacked up brain to followed by the backup path, the init output, Re-syncing brain repo..., and finally Reinit complete. To roll back: with an mv command.
nexusbrain embed --staleYou should seeThe command embeds the remaining chunks, or finds nothing left to do.
nexusbrain doctorYou should seeembedding_width_consistency is [OK] and the embeddings check shows your coverage.
| Flag | What it does |
|---|---|
--embedding-model <provider:model> | New embedding model. Defaults to embedding_model in the config file. |
--embedding-dimensions <N> | New dimension count. Defaults to embedding_dimensions in the config file. |
--path <path> | Active brain path. Default: ~/.nexusbrain/brain.pglite. |
--yes / -y | Skip the confirmation prompt. Required when there is no interactive terminal. |
--no-sync | Skip the nexusbrain sync after init. Run it yourself later. |
--json | Print structured JSON on stdout for scripts. |
Sync re-imports what is in your brain repo on disk. Pages that only existed in the database, with no markdown file, do not come back. If you are unsure, run nexusbrain export --dir ./export first. The old brain stays at brain.pglite.bak so you can roll back.
This is the same procedure as reinit-pglite, one step at a time. The doctor message prints these exact commands with your real brain path filled in.
mv ~/.nexusbrain/brain.pglite ~/.nexusbrain/brain.pglite.bakYou should seeThe folder brain.pglite.bak exists and brain.pglite does not.
nexusbrain init --pglite --embedding-model openai:text-embedding-3-large --embedding-dimensions 1536You should seeInit finishes and creates a fresh brain.pglite.
nexusbrain syncYou should seeA summary such as First sync complete. with the number of files imported.
nexusbrain embed --staleYou should seeChunks are embedded with the new model. nexusbrain doctor then shows the width check as [OK].
Postgres can change the column in place, so your pages stay and only the vectors are rebuilt. nexusbrain reinit-pglite refuses to run here, because wiping would delete the whole brain.
The simplest path is nexusbrain migrate embeddings. It checks the new provider with one live call before changing anything, rebuilds the column, updates the config, and re-embeds. If it is interrupted, run the same command again and it continues where it stopped.
nexusbrain migrate embeddings --to openai:text-embedding-3-large --dim 1536You should seeThe migration plan, then the prompt to confirm. Without an interactive terminal, add --yes.
You should seeA line such as [migrate] schema rebuilt at 1536d, followed by embedding progress.
| Flag | What it does |
|---|---|
--to <provider:model> | Target embedding model. |
--dim <N> | Target dimensions. Defaults to the provider recipe width. |
--dry-run | Plan and cost estimate only. Changes nothing. |
--yes | Skip the confirmation. Required non-interactively. |
--no-embed | Rebuild schema and config but skip the re-embed. Run nexusbrain embed --stale --include-null-signature later. |
--batch-size <N> | Stale-chunk batch size for the re-embed. Default 2000. |
--pace[=mode] | Database pacing for the re-embed: off, gentle, balanced or aggressive. |
If you prefer to run the SQL yourself, this is the recipe the brain prints. Replace 1536 with your new size. The embeddings are set to NULL before the ALTER because pgvector refuses to convert existing vectors between sizes.
BEGIN;
DROP INDEX IF EXISTS idx_chunks_embedding;
UPDATE content_chunks SET embedding = NULL, embedded_at = NULL;
ALTER TABLE content_chunks ALTER COLUMN embedding TYPE vector(1536);
CREATE INDEX IF NOT EXISTS idx_chunks_embedding
ON content_chunks USING hnsw (embedding vector_cosine_ops);
COMMIT;You should seeThe transaction commits without errors.
nexusbrain init --supabase --embedding-model openai:text-embedding-3-large --embedding-dimensions 1536You should seeInit completes with the new embedding settings.
nexusbrain embed --staleYou should seeChunks are embedded. nexusbrain doctor then shows embedding_width_consistency as [OK].
pgvector can only build the HNSW search index for up to 2000 dimensions. Above that, skip the CREATE INDEX line. Search still works using an exact scan.
nexusbrain reinit-pglite is for PGLite brains only (current engine: postgres).Your brain runs on Postgres. Use nexusbrain migrate embeddings or the manual SQL recipe above.
Backup already exists at ... .bak. Move or delete it first to avoid clobbering your previous rollback target.A backup from an earlier attempt is still there. Move it somewhere safe or delete it once you no longer need it, then run the command again.
Non-TTY environment requires --yes to confirm destruction.You ran reinit-pglite from a script or agent. Add --yes if you are sure.
--embedding-model <provider:model> is required (no embedding_model in the config file to default from).Pass --embedding-model and --embedding-dimensions explicitly. The same applies to the matching --embedding-dimensions message.
[config] embedding_model is a file-plane field that sizes the schema.nexusbrain config set cannot change the embedding model. Follow the local engine or Postgres procedure in this guide instead.
nexusbrain serve.Stop nexusbrain serve, then run the command again. See Running serve and sync together.
Warning: sync after reinit failed and the brain is empty.The new brain was created. Run nexusbrain sync to import your pages, then nexusbrain embed --stale.
Move the new brain out of the way, then move the backup back with the mv command printed after Reinit complete. To roll back:.