Skip to content

Race condition on CREATE EXTENSION vector in PGEngine (missing advisory lock) #329

Description

Summary

PGEngine.ainit_vectorstore_table (v2) is missing the advisory lock that the legacy PGVector.create_vector_extension uses, so the two code paths can race on CREATE EXTENSION IF NOT EXISTS vector and hit a duplicate-key error.

Where

File Behavior
langchain_postgres/vectorstores.py (_create_vector_extension) Takes pg_advisory_xact_lock(1573678846307946496) before CREATE EXTENSION IF NOT EXISTS vector
langchain_postgres/v2/engine.py (ainit_vectorstore_table, ~line 215) Runs the same CREATE EXTENSION IF NOT EXISTS vector without any lock

Why it matters

The advisory lock only serializes callers that take the same lock. Since the v2 path takes no lock at all, it provides zero protection against Postgres's known race where concurrent sessions can both pass the "not exists" check and then collide on insert:

duplicate key value violates unique constraint "pg_extension_name_index"

This can be hit whenever an application initializes a PGEngine-based store concurrently with another PGEngine/PGVector initialization, e.g.:

  • Two asyncio.gather'd ainit_vectorstore_table calls
  • A PGVectorStore init racing a legacy PGVector init

How we found it

While maintaining a TypeScript port of this package, our test runner executes test files in parallel by default, which reliably reproduces the race between the unlocked PGEngine path and the locked legacy PGVector path. The same asymmetry exists in this Python source, so concurrent use in a real application (not just tests) could hit it too.

Suggested fix

Wrap the CREATE EXTENSION IF NOT EXISTS vector call in v2/engine.py with the same pg_advisory_xact_lock (reusing the existing lock key or helper) so both code paths are mutually exclusive.

Happy to send a PR if that's useful.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions