cocoindex-io/cocoindex · error · ValueError

Invalid Qdrant point ID {raw!r}: strings must be UUIDs. {_PO

Error message

Invalid Qdrant point ID {raw!r}: strings must be UUIDs. {_POINT_ID_RULE}

What it means

Qdrant accepts string point IDs only when they are valid UUIDs. declare_point attempts uuid.UUID(raw) on every string ID and raises this ValueError (with the point-ID rule text) for anything that is not a UUID in a form Python's uuid can parse. This fails at declare time rather than with an opaque Qdrant transport error at upsert.

Source

Thrown at python/cocoindex/connectors/qdrant/_target.py:758

    Qdrant only accepts unsigned 64-bit integers and UUIDs (any textual
    form: hyphenated, 32-char hex, or URN); everything else is rejected at
    upsert time with an opaque transport error, so fail at declare time
    with an actionable one instead.
    """
    if isinstance(raw, int):
        if not 0 <= raw < 1 << 64:
            raise ValueError(
                f"Invalid Qdrant point ID {raw!r}: out of unsigned 64-bit range. "
                f"{_POINT_ID_RULE}"
            )
        return raw
    if isinstance(raw, uuid.UUID):
        return str(raw)
    if isinstance(raw, str):
        try:
            uuid.UUID(raw)
        except ValueError:
            raise ValueError(
                f"Invalid Qdrant point ID {raw!r}: strings must be UUIDs. "
                f"{_POINT_ID_RULE}"
            ) from None
        return raw
    raise ValueError(
        f"Invalid Qdrant point ID of type {type(raw).__name__}. {_POINT_ID_RULE}"
    )


__all__ = [
    "CollectionSchema",
    "CollectionTarget",
    "PointStruct",
    "QdrantSparseVectorDef",
    "QdrantVectorDef",
    "collection_target",
    "create_client",
    "declare_collection_target",

View on GitHub (pinned to e84aa99b32)

Solutions

  1. Convert the key to a UUID: str(uuid.uuid5(uuid.NAMESPACE_URL, f"doc/{key}")) for a stable, deterministic ID.
  2. If you have a numeric ID, pass it as a Python int (in [0, 2^64)) instead of a string.
  3. Validate with `str(uuid.UUID(s))` before declaring if the string is supposed to be a UUID.
  4. Prepend the accepted prefix (urn:uuid: or braces) is fine only if the rest is a valid UUID — otherwise regenerate.

Example fix

// before
await target.declare_point(id="doc-123", ...)
// after
import uuid
await target.declare_point(id=str(uuid.uuid5(uuid.NAMESPACE_URL, "doc/doc-123")), ...)
Defensive patterns

Strategy: validation

Validate before calling

import uuid
def _ensure_uuid_str(s):
    uuid.UUID(s)  # raises if not a UUID
    return s

Type guard

def is_uuid_string(s):
    if not isinstance(s, str): return False
    try: uuid.UUID(s); return True
    except ValueError: return False

Try / catch

try:
    await target.declare_point(id=pid, ...)
except ValueError as e:
    pid = str(uuid.uuid5(uuid.NAMESPACE_URL, f"doc/{raw_key}"))
    await target.declare_point(id=pid, ...)

Prevention

When it happens

Trigger: Calling declare_point with a string point ID like "doc-123", "my/file.md", a numeric string "42", or any non-UUID string; also UUID-ish strings with invalid formatting (wrong length/characters).

Common situations: Passing file paths or natural keys directly as point IDs; storing integer IDs as strings; truncated or malformed UUIDs copied from logs.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of cocoindex-io/cocoindex@e84aa99b32 (2026-09-08). Data as JSON: /api/errors/fe7b97b8682d635f. Report an issue: GitHub.