cocoindex-io/cocoindex · error · ValueError

Unsupported pgvector metric '{metric}' for PostgreSQL type '

Error message

Unsupported pgvector metric '{metric}' for PostgreSQL type '{pg_type}'.

What it means

Raised by `_pgvector_op_class` when the requested similarity metric has no entry in `_PGVECTOR_OP_CLASS` for the column's pgvector type base (`vector` or `halfvec`). Each pgvector type supports a fixed set of metrics (cosine, l2, ip); anything else (e.g. 'dot', 'euclidean', 'hamming') is rejected.

Source

Thrown at python/cocoindex/connectors/postgres/_target.py:476

    "halfvec": {
        "cosine": "halfvec_cosine_ops",
        "l2": "halfvec_l2_ops",
        "ip": "halfvec_ip_ops",
    },
}


def _pgvector_op_class(column: str, pg_type: str, metric: str) -> str:
    type_base = _pgvector_type_base(pg_type)
    if type_base is None:
        raise ValueError(
            f"Column '{column}' has PostgreSQL type '{pg_type}', which is not a pgvector type."
        )

    try:
        return _PGVECTOR_OP_CLASS[type_base][metric]
    except KeyError as e:
        raise ValueError(
            f"Unsupported pgvector metric '{metric}' for PostgreSQL type '{pg_type}'."
        ) from e


class _VectorIndexSpec(NamedTuple):
    column: str
    metric: str
    op_class: str
    method: str
    lists: int | None
    m: int | None
    ef_construction: int | None


_VectorIndexFingerprint = bytes


class _VectorIndexAction(NamedTuple):

View on GitHub (pinned to e84aa99b32)

Solutions

  1. Use one of the supported metric strings: 'cosine', 'l2', or 'ip'.
  2. Map your desired metric: dot product -> 'ip', euclidean -> 'l2', cosine similarity -> 'cosine'.
  3. Lowercase the metric string before passing it.
  4. Check `_PGVECTOR_OP_CLASS` in the connector source for the exact supported matrix.

Example fix

// before
table.declare_vector_index(column="embedding", metric="Euclid")
// after
table.declare_vector_index(column="embedding", metric="l2")
Defensive patterns

Strategy: validation

Validate before calling

SUPPORTED_METRICS = {"cosine", "l2", "ip"}
# before calling:
# assert metric.lower() in SUPPORTED_METRICS

Type guard

from typing import Literal
Metric = Literal["cosine", "l2", "ip"]
def is_metric(m: str) -> bool:
    return m in {"cosine", "l2", "ip"}

Try / catch

try:
    table.declare_vector_index(column=col, metric=metric)
except ValueError as e:
    if "Unsupported pgvector metric" in str(e):
        logger.error("Metric %r invalid; use cosine/l2/ip", metric)
    else:
        raise

Prevention

When it happens

Trigger: Calling `declare_vector_index(column=..., metric='dot')` or any metric string other than exactly 'cosine', 'l2', or 'ip' on a vector/halfvec column; a typo like 'cosine_distance' or mixed-case 'Cosine'.

Common situations: Translating metric names from another vector database (Qdrant's 'Euclid'/'Dot') into this API; case-sensitivity mistakes; passing an enum's repr instead of the string.

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 cocoindex-io/cocoindex@e84aa99b32 (2026-09-08). Data as JSON: /api/errors/c0527ed067bd552b. Report an issue: GitHub.