{"record":{"id":"91a42349325557e7","repo":"FlowiseAI/Flowise","slug":"unknown-distance-strategy-distancestrategy","errorCode":null,"errorMessage":"Unknown distance strategy: ${distanceStrategy}","messagePattern":"Unknown distance strategy: (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/components/nodes/vectorstores/Postgres/driver/TypeORM.ts","lineNumber":174,"sourceCode":"            await this.ensureTableInDatabase(instance, effectiveTablePath)\n            return (instance.addVectors as any)(await this.getEmbeddings().embedDocuments(texts), documents, options)\n        }\n\n        return instance\n    }\n\n    get computedOperatorString() {\n        const { distanceStrategy = 'cosine' } = this.nodeData.inputs || {}\n\n        switch (distanceStrategy) {\n            case 'cosine':\n                return '<=>'\n            case 'innerProduct':\n                return '<#>'\n            case 'euclidean':\n                return '<->'\n            default:\n                throw new Error(`Unknown distance strategy: ${distanceStrategy}`)\n        }\n    }\n\n    /**\n     * Ensures the table exists in the database with the correct schema.\n     * Creates the pgvector extension and table if they don't exist.\n     */\n    async ensureTableInDatabase(instance: TypeORMVectorStore, tablePath: string): Promise<void> {\n        await instance.appDataSource.query('CREATE EXTENSION IF NOT EXISTS vector;')\n        await instance.appDataSource.query(`\n            CREATE TABLE IF NOT EXISTS ${tablePath} (\n                \"id\" uuid NOT NULL DEFAULT gen_random_uuid() PRIMARY KEY,\n                \"pageContent\" text,\n                metadata jsonb,\n                embedding vector\n            );\n        `)\n    }","sourceCodeStart":156,"sourceCodeEnd":192,"githubUrl":"https://github.com/FlowiseAI/Flowise/blob/abe4a8601a058047b350c260676826e21dd14101/packages/components/nodes/vectorstores/Postgres/driver/TypeORM.ts#L156-L192","documentation":"The Postgres/TypeORM pgvector driver maps a `distanceStrategy` node input to a pgvector distance operator via the `computedOperatorString` getter. Only three strategies are recognized: 'cosine' (<=>), 'innerProduct' (<#>), and 'euclidean' (<->). Any other value falls through to the default branch and throws. The comparison is exact and case-sensitive, so even a correctly-named strategy with different casing or surrounding whitespace will be rejected.","triggerScenarios":"Supplying a `distanceStrategy` input that is not exactly 'cosine', 'innerProduct', or 'euclidean' — e.g. 'Cosine', 'dot', 'manhattan', 'l2', a typo like 'cosin', or an empty string. The getter is invoked whenever the vector store computes the distance operator for similarity search.","commonSituations":"Node dropdown options drifting out of sync with this switch after an upgrade; user typing a free-text strategy; case mismatch ('Cosine' vs 'cosine'); migrating from another store whose strategy names differ (e.g. pgvector docs use 'l2'); trailing whitespace from a templated config value.","solutions":["Set `distanceStrategy` to exactly one of: 'cosine', 'innerProduct', or 'euclidean'.","Trim and lowercase the value before it reaches the node: `distanceStrategy.trim().toLowerCase()` mapping to the canonical form.","If the node UI exposes a value not handled here, update the dropdown to only the three supported values.","To support a new strategy, add a case returning the correct pgvector operator and update the node's allowed-values list."],"exampleFix":"// before\nconst { distanceStrategy = 'cosine' } = this.nodeData.inputs || {}\nswitch (distanceStrategy) { /* ... */ default: throw new Error(`Unknown distance strategy: ${distanceStrategy}`) }\n\n// after (normalize + safe default)\nconst raw = String(this.nodeData.inputs?.distanceStrategy ?? 'cosine').trim().toLowerCase()\nconst strategy = raw === 'innerproduct' ? 'innerProduct' : raw\nswitch (strategy) {\n  case 'cosine': return '<=>'\n  case 'innerProduct': return '<#>'\n  case 'euclidean': return '<->'\n  default: throw new Error(`Unknown distance strategy: ${distanceStrategy}. Supported: cosine, innerProduct, euclidean`)\n}","handlingStrategy":"validation","validationCode":"const ALLOWED = ['cosine', 'innerProduct', 'euclidean'] as const\nfunction normalizeDistanceStrategy(raw: unknown): typeof ALLOWED[number] {\n  const s = String(raw ?? 'cosine').trim().toLowerCase()\n  if (s === 'innerproduct') return 'innerProduct'\n  if ((ALLOWED as readonly string[]).includes(s)) return s as typeof ALLOWED[number]\n  throw new Error(`Unsupported distanceStrategy '${String(raw)}'. Use one of: ${ALLOWED.join(', ')}`)\n}","typeGuard":"function isDistanceStrategy(v: unknown): v is 'cosine' | 'innerProduct' | 'euclidean' {\n  return v === 'cosine' || v === 'innerProduct' || v === 'euclidean'\n}","tryCatchPattern":"try { const op = computedOperatorString } catch (e) { /* surface supported list */ throw new Error(`${(e as Error).message}. Supported: cosine, innerProduct, euclidean`) }","preventionTips":["Constrain the node dropdown to the three supported strategies.","Normalize incoming input (trim + lowercase) before the switch.","Reject unsupported values at the API boundary, not deep in the getter."],"tags":["postgres","pgvector","input-validation","configuration","typescript"],"backgroundTag":null,"analyzedSha":"abe4a8601a058047b350c260676826e21dd14101","analyzedAt":"2026-08-12T16:04:40.823Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}