{"record":{"id":"395ee0921db64d50","repo":"supermemoryai/supermemory","slug":"vectors-must-have-the-same-length","errorCode":null,"errorMessage":"Vectors must have the same length","messagePattern":"Vectors must have the same length","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/lib/similarity.ts","lineNumber":13,"sourceCode":"// Utility functions for calculating semantic similarity between documents and memories\n\n/**\n * Calculate cosine similarity between two normalized vectors (unit vectors)\n * Since all embeddings in this system are normalized using normalizeEmbeddingFast,\n * cosine similarity equals dot product for unit vectors.\n */\nexport const cosineSimilarity = (\n\tvectorA: number[],\n\tvectorB: number[],\n): number => {\n\tif (vectorA.length !== vectorB.length) {\n\t\tthrow new Error(\"Vectors must have the same length\")\n\t}\n\n\tlet dotProduct = 0\n\n\tfor (let i = 0; i < vectorA.length; i++) {\n\t\tconst vectorAi = vectorA[i]\n\t\tconst vectorBi = vectorB[i]\n\t\tif (\n\t\t\ttypeof vectorAi !== \"number\" ||\n\t\t\ttypeof vectorBi !== \"number\" ||\n\t\t\tisNaN(vectorAi) ||\n\t\t\tisNaN(vectorBi)\n\t\t) {\n\t\t\tthrow new Error(\"Vectors must contain only numbers\")\n\t\t}\n\t\tdotProduct += vectorAi * vectorBi\n\t}\n","sourceCodeStart":1,"sourceCodeEnd":31,"githubUrl":"https://github.com/supermemoryai/supermemory/blob/d436792e777a99865939dd543c8d1a16d57f54ec/packages/lib/similarity.ts#L1-L31","documentation":"cosineSimilarity throws when the two vectors passed in have different lengths. Dot product (and cosine similarity) is only defined for vectors of the same dimension, so this is a precondition check on the mathematical operation.","triggerScenarios":"Calling cosineSimilarity with embeddings from different models (e.g. a 1536-dim OpenAI vector vs a 768-dim vector), or comparing a vector against an empty/undefined array coerced to a different length.","commonSituations":"Switching embedding providers without re-embedding stored vectors; mixing stored embeddings with freshly generated ones from a different model version; passing a truncated or malformed stored vector.","solutions":["Ensure both vectors come from the same embedding model and version","Add a length check before calling and log/skip mismatched pairs","Re-embed stored data after changing embedding models","Validate vector dimension at ingestion time"],"exampleFix":"// before\nconst score = cosineSimilarity(storedVec, queryVec)\n\n// after\nif (storedVec.length !== queryVec.length) {\n  console.warn(`dim mismatch: ${storedVec.length} vs ${queryVec.length}`)\n  continue\n}\nconst score = cosineSimilarity(storedVec, queryVec)","handlingStrategy":"validation","validationCode":"if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length) { throw new TypeError(`Vector length mismatch: ${a?.length} vs ${b?.length}`) }","typeGuard":"const isVectorOf = (len: number) => (v: unknown): v is number[] => Array.isArray(v) && v.length === len && v.every((x) => typeof x === 'number' && Number.isFinite(x))","tryCatchPattern":"try { score = cosineSimilarity(a, b) } catch { continue /* skip incomparable vectors */ }","preventionTips":["Pin one embedding model/version for both storage and query","Store model+dimension metadata alongside each vector","Re-embed everything after any embedding model change"],"tags":["math","embedding","validation","similarity"],"backgroundTag":"vector-dimension-mismatch","analyzedSha":"d436792e777a99865939dd543c8d1a16d57f54ec","analyzedAt":"2026-08-28T18:04:46.947Z","schemaVersion":2},"datasetVersion":"2026-08-28T21:17:43.275Z"}