mastra-ai/mastra · error · HTTPException

Invalid metric. Must be one of: cosine, euclidean, dotproduc

Error message

Invalid metric. Must be one of: cosine, euclidean, dotproduct

What it means

This HTTP 400 error is thrown by the createIndex handler when a metric is supplied but is not one of the three supported similarity metrics: 'cosine', 'euclidean', or 'dotproduct'. The check runs after the indexName/dimension validation and before any vector store call. Omitting metric entirely is allowed (the store default applies); only an invalid explicit value triggers it.

Source

Thrown at packages/server/src/server/handlers/vector.ts:100

}

// Create index
export async function createIndex({
  mastra,
  vectorName,
  indexName,
  dimension,
  metric,
}: Pick<VectorContext, 'mastra' | 'vectorName'> & CreateIndexRequest) {
  try {
    if (!indexName || typeof dimension !== 'number' || dimension <= 0) {
      throw new HTTPException(400, {
        message: 'Invalid request index, indexName and positive dimension number are required.',
      });
    }

    if (metric && !['cosine', 'euclidean', 'dotproduct'].includes(metric)) {
      throw new HTTPException(400, { message: 'Invalid metric. Must be one of: cosine, euclidean, dotproduct' });
    }

    const vector = getVector(mastra, vectorName);
    await vector.createIndex({ indexName, dimension, metric });
    return { success: true };
  } catch (error) {
    return handleError(error, 'Error creating index');
  }
}

// Query vectors
export async function queryVectors({
  mastra,
  vectorName,
  indexName,
  queryVector,
  topK,
  filter,

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Use exactly one of: 'cosine', 'euclidean', 'dotproduct' (lowercase).
  2. Map provider-specific metric names to these three values before sending.
  3. If you don't need a specific metric, omit the metric field entirely to use the store default.
  4. Check for stray whitespace or casing in the metric value (trim and lowercase).

Example fix

// before
await createIndex({ indexName: 'docs', dimension: 1536, metric: 'inner_product' });
// after
await createIndex({ indexName: 'docs', dimension: 1536, metric: 'dotproduct' });
Defensive patterns

Strategy: validation

Validate before calling

const METRICS = ['cosine', 'euclidean', 'dotproduct'] as const;
function assertMetric(metric) {
  if (metric !== undefined && !METRICS.includes(metric)) throw new TypeError(`metric must be one of ${METRICS.join(', ')}`);
}

Type guard

function isVectorMetric(m) { return m === undefined || m === 'cosine' || m === 'euclidean' || m === 'dotproduct'; }

Try / catch

try {
  await client.createIndex({ indexName, dimension, metric });
} catch (e) {
  if (e.status === 400 && /Invalid metric/.test(e.message)) {
    console.error(`Unsupported metric '${metric}'; use cosine, euclidean, or dotproduct`);
  }
  throw e;
}

Prevention

When it happens

Trigger: POSTing to create-index with metric set to values like 'dot', 'euclidean2', 'COSINE' (case-sensitive), 'cosine similarity', or a metric copied from a different vector provider (e.g. 'inner_product', 'l2').

Common situations: Porting code from another vector database (pgvector/Pinecone use different metric names); uppercase metric from an enum or UI dropdown; typos like 'dotProduct' (camelCase not accepted).

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/abedde87fcc4ace3. Report an issue: GitHub.