The ElizaOS pgvector dimension mismatch crash (‘vector length 1536 does not match column dimension 768’) occurs when an AI agent changes its embedding model (such as migrating from OpenAI text-embedding-3-small to Ollama or BGE) without migrating the PostgreSQL memory table schema. Because the memories table vector column is fixed at schema creation, inserting vector arrays with mismatched dimensions throws a fatal error. Altering the column dimension resolves the crash.
Before executing state changes or signing transactions, verify your cryptographic parameters using our interactive ERC-4337 Calldata Decoder utility.
Architectural Breakdown: Strict pgvector Dimensionality Constraints
In PostgreSQL, the pgvector extension defines vector columns with a mandatory compile-time or schema-level length parameter:
$$\text{embedding} \quad \text{vector}(D)$$
Why pgvector Forbids Dimension Mismatches
- Memory Representation: pgvector stores vectors as contiguous arrays of single-precision floating-point numbers ($4 \times D$ bytes). Index types like HNSW (Hierarchical Navigable Small World) and IVFFlat construct distance graphs based on fixed-length metric calculations (Cosine, Euclidean $L_2$, or Inner Product).
- Mathematical Incompatibility: Calculating the cosine distance: $$\cos(\theta) = \frac{\mathbf{u} \cdot \mathbf{v}}{|\mathbf{u}|_2 |\mathbf{v}|_2}$$ is mathematically undefined when $\mathbf{u} \in \mathbb{R}^{768}$ and $\mathbf{v} \in \mathbb{R}^{1536}$.
- ElizaOS Adapter Schema Hardcoding: Older versions of
@elizaos/adapter-postgrescreate thememoriestable withembedding vector(1536)by default. When an Ollama model emits a 768-element array, the PostgreSQL wire protocol parser halts execution.
Step-by-Step Resolution Protocol
To resolve the dimension mismatch without wiping your entire Postgres database or corrupting existing memories, execute this three-stage migration.
1. Execute Non-Destructive PostgreSQL Column Alteration
Connect to your PostgreSQL database instance (via psql or pgAdmin) and alter the vector column to the target dimensionality of your new model.
Option A: Clean Cutover for Fresh Agents (Drops Old Indices)
If you are developing or can afford to regenerate historical embeddings:
-- Connect to your eliza database
\c eliza_db;
-- 1. Drop existing HNSW or IVFFlat vector index
DROP INDEX IF EXISTS memories_embedding_hnsw_idx;
DROP INDEX IF EXISTS memories_embedding_idx;
-- 2. Alter column to match your new embedding dimension (e.g., 768 for nomic-embed-text)
ALTER TABLE memories
ALTER COLUMN embedding TYPE vector(768);
-- 3. Recreate the high-performance HNSW index for the new dimension
CREATE INDEX memories_embedding_hnsw_idx
ON memories
USING hnsw (embedding vector_cosine_ops)
WITH (m = 16, ef_construction = 64);
Option B: Dual-Column Architecture (Preserves Historical Memories)
If you have critical agent conversations embedded at 1536 dimensions that must be preserved:
-- Add a dedicated column for the local model
ALTER TABLE memories ADD COLUMN IF NOT EXISTS embedding_768 vector(768);
-- Create an HNSW index for the secondary column
CREATE INDEX IF NOT EXISTS memories_embedding_768_hnsw_idx
ON memories
USING hnsw (embedding_768 vector_cosine_ops);
2. Configure ElizaOS Character Configuration
Ensure your characters/your-agent.character.json file explicitly declares the embedding model and dimensions so the runtime does not default to OpenAI parameters:
{
"name": "SentinelAgent",
"modelProvider": "ollama",
"settings": {
"voice": {
"model": "en_US-male-medium"
},
"embeddingModel": "nomic-embed-text",
"embeddingDimension": 768
},
"plugins": []
}
3. Implement Runtime Defensive Embedding Adapter
In custom TypeScript scripts or agent extensions, intercept embeddings before dispatch to PostgreSQL to catch length anomalies before they trigger SQL transaction rollbacks:
// src/utils/embeddingGuard.ts
export function validateEmbeddingDimension(embedding: number[], expectedDim: number): number[] {
if (!Array.isArray(embedding)) {
throw new Error('EMBEDDING_ERROR: Output is not a valid numerical array.');
}
if (embedding.length !== expectedDim) {
console.error(
`[EmbeddingGuard] Critical dimension mismatch! Got ${embedding.length}, expected ${expectedDim}.`
);
// Defensive strategy: If smaller, pad with zeros; if larger, slice (temporary fallback)
if (embedding.length < expectedDim) {
const padded = new Array(expectedDim).fill(0);
for (let i = 0; i < embedding.length; i++) padded[i] = embedding[i];
return padded;
} else {
return embedding.slice(0, expectedDim);
}
}
return embedding;
}
Model Dimension Reference Matrix
| Provider | Embedding Model Name | Vector Dimensions | Recommended HNSW Distance |
|---|---|---|---|
| OpenAI | text-embedding-3-small | 1536 (or customizable) | vector_cosine_ops |
| OpenAI | text-embedding-3-large | 3072 | vector_cosine_ops |
| Ollama | nomic-embed-text | 768 | vector_cosine_ops |
| Ollama | mxbai-embed-large | 1024 | vector_cosine_ops |
| HuggingFace | BAAI/bge-small-en-v1.5 | 384 | vector_cosine_ops |
| HuggingFace | BAAI/bge-large-en-v1.5 | 1024 | vector_cosine_ops |
[!TIP] Diagnostic Verification & Air-Gapped Testing: Before executing state changes or broad recovery steps, cross-reference failure parameters with our companion guide on ElizaOS Failed to Parse JSON From OpenAI Response and verify transaction calldata or cryptographic envelopes using the Master Web3 & RPC Error Code Directory.
Frequently Asked Questions
Q: Why doesn’t ElizaOS automatically detect the embedding dimension on startup?
In current versions of @elizaos/core, the database schema migration runs once during initial deployment (initDatabase). If the table was initialized under OpenAI’s 1536-dimension schema, subsequent agent launches assume the database column matches whatever model is defined in the character file.
Q: Can I use text-embedding-3-small with 768 dimensions directly?
Yes. OpenAI’s text-embedding-3 models support native dimension reduction via MRL (Matryoshka Representation Learning). You can pass { dimensions: 768 } in your API options, allowing you to match a 768-dimension schema without switching away from OpenAI.
Q: What happens if I query the database with a zero-padded vector?
Zero-padding preserves array length to avoid database errors, but it degrades retrieval accuracy because the geometric cosine angle is distorted. Zero-padding should only be used as a non-crashing fail-safe while a background script backfills genuine embeddings.