Guides / Brain

Changing the embedding model

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.

Time
15 minutes of setup, plus re-embedding time for your brain
For
Anyone switching embedding providers, models or dimensions on an existing brain

Before you start

  • A brain created with nexusbrain init, on either the local engine (PGLite) or Postgres.
  • An API key for the new embedding provider, available to the brain.
  • The new model name in provider:model form (for example openai:text-embedding-3-large) and its dimension count.
  • On the local engine: nexusbrain serve stopped, because only one process can open the local database at a time.

01Understand where the size is set

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.

EngineHow the column is rebuiltCommand
Local (PGLite)Wipe and re-create the brain, then re-import from your brain reponexusbrain reinit-pglite
PostgresRebuild the column in place, keeping your pagesnexusbrain migrate embeddings or the SQL recipe
Warning

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.

02Detect a mismatch and estimate the cost

  1. Run the health check.

    Do not add --fast. That flag skips every database check, including the embedding checks.

    nexusbrain doctor

    You 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.

  2. Look for the width warning.

    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).

  3. Estimate the re-embedding cost before you change anything.

    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-run

    You 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 itMessage
nexusbrain doctorEmbedding dimension mismatch detected.
nexusbrain embed or nexusbrain initRefusing to silently re-template existing brain.
BothExisting column: vector(N) and Requested: vector(M)
Tip

Set a budget before you start. See Spend controls for how caps and cost gates work.

03Rebuild on the local engine with one command

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.

  1. Stop 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.

  2. Run the reinit command with the new model and size.

    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 1280

    You 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):.

  3. Type 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.

  4. Embed anything the sync left pending.

    nexusbrain embed --stale

    You should seeThe command embeds the remaining chunks, or finds nothing left to do.

  5. Confirm the fix.

    nexusbrain doctor

    You should seeembedding_width_consistency is [OK] and the embeddings check shows your coverage.

FlagWhat 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 / -ySkip the confirmation prompt. Required when there is no interactive terminal.
--no-syncSkip the nexusbrain sync after init. Run it yourself later.
--jsonPrint structured JSON on stdout for scripts.
Warning

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.

04Rebuild on the local engine by hand

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.

  1. Move the current brain aside as a backup.

    mv ~/.nexusbrain/brain.pglite ~/.nexusbrain/brain.pglite.bak

    You should seeThe folder brain.pglite.bak exists and brain.pglite does not.

  2. Create a new brain at the new size.

    nexusbrain init --pglite --embedding-model openai:text-embedding-3-large --embedding-dimensions 1536

    You should seeInit finishes and creates a fresh brain.pglite.

  3. Re-import your brain repo from disk.

    nexusbrain sync

    You should seeA summary such as First sync complete. with the number of files imported.

  4. Rebuild the embeddings.

    nexusbrain embed --stale

    You should seeChunks are embedded with the new model. nexusbrain doctor then shows the width check as [OK].

05Rebuild on Postgres

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.

  1. Run the migration.

    nexusbrain migrate embeddings --to openai:text-embedding-3-large --dim 1536

    You should seeThe migration plan, then the prompt to confirm. Without an interactive terminal, add --yes.

  2. Confirm and wait for the re-embed.

    You should seeA line such as [migrate] schema rebuilt at 1536d, followed by embedding progress.

FlagWhat it does
--to <provider:model>Target embedding model.
--dim <N>Target dimensions. Defaults to the provider recipe width.
--dry-runPlan and cost estimate only. Changes nothing.
--yesSkip the confirmation. Required non-interactively.
--no-embedRebuild 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.

06Use the manual SQL recipe on Postgres

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.

  1. Run the column change in one transaction.

    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.

  2. Save the new model in the config.

    nexusbrain init --supabase --embedding-model openai:text-embedding-3-large --embedding-dimensions 1536

    You should seeInit completes with the new embedding settings.

  3. Rebuild the embeddings.

    nexusbrain embed --stale

    You should seeChunks are embedded. nexusbrain doctor then shows embedding_width_consistency as [OK].

Note

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.

07Troubleshooting

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.

The command says the local database is already open through 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.

You want to undo a reinit.

Move the new brain out of the way, then move the backup back with the mv command printed after Reinit complete. To roll back:.