Skip to content

fix: use uuid4 (not uuid1) for auto-generated ids in async constructors#314

Open
Andrew Chen (chuenchen309) wants to merge 1 commit into
langchain-ai:mainfrom
chuenchen309:fix/afrom-uuid4-parity
Open

fix: use uuid4 (not uuid1) for auto-generated ids in async constructors#314
Andrew Chen (chuenchen309) wants to merge 1 commit into
langchain-ai:mainfrom
chuenchen309:fix/afrom-uuid4-parity

Conversation

@chuenchen309

Copy link
Copy Markdown

Problem

PGVector's sync constructor path (__from, used by from_texts /
from_embeddings / from_documents) generates auto-assigned document ids with
uuid.uuid4():

# __from
if ids is None:
    ids = [str(uuid.uuid4()) for _ in texts]

The async path (__afrom, used by afrom_texts / afrom_embeddings /
afrom_documents) instead used uuid.uuid1():

# __afrom
if ids is None:
    ids = [str(uuid.uuid1()) for _ in texts]

uuid1 encodes the host's MAC address and a timestamp. So when a caller
lets the store auto-generate ids (the common case), the async API:

  1. produces ids that are inconsistent with the random ids the sync API
    produces for the same call, and
  2. leaks the server's hardware address and record-creation time into the
    ids that get stored in the DB and returned to callers.

These ids are not discarded — __afrom passes them into aadd_embeddings,
which writes them as the primary-key id. aadd_embeddings itself already uses
uuid4 for its own auto-generation, so this lone uuid1 looks like an
oversight rather than a deliberate choice.

Fix

Use uuid.uuid4() in __afrom, matching __from and aadd_embeddings.

Test

Added tests/unit_tests/v1/test_afrom_uuid.py, a pure-Python test (no live
Postgres): constructing with async_mode=True defers __post_init__ so no
connection is opened, and aadd_embeddings is stubbed to capture the generated
ids. It asserts every auto-generated id is a UUIDv4. Fails before the change
(version == 1), passes after.

$ python -m pytest tests/unit_tests/v1/test_afrom_uuid.py -q
1 passed

ruff check passes on the changed files.


Disclosure: I used AI assistance (Claude) to help locate this sync/async
parity gap and draft the test. I reviewed the change, ran the test suite, and
take responsibility for its correctness.

PGVector's sync constructor path (`__from`) mints auto-generated document
ids with `uuid.uuid4()`, but the async path (`__afrom`, used by
`afrom_texts`/`afrom_embeddings`/`afrom_documents`) used `uuid.uuid1()`.

uuid1 encodes the host MAC address and a timestamp, so ids generated via
the async API (a) diverge from the random ids the sync API produces and
(b) leak the server's hardware address and record-creation time into the
stored/returned ids. `aadd_embeddings` itself already uses uuid4, so this
lone uuid1 was an oversight rather than intentional.

Align `__afrom` with the sync path and the rest of the module by using
uuid4.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant