Skip to content

fix(oracle): honor explicit wallet_password="" for auto-login wallets (closes #289)#290

Merged
fede-kamel merged 1 commit into
mainfrom
fix/289-wallet-password-empty-string
May 30, 2026
Merged

fix(oracle): honor explicit wallet_password="" for auto-login wallets (closes #289)#290
fede-kamel merged 1 commit into
mainfrom
fix/289-wallet-password-empty-string

Conversation

@fede-kamel
Copy link
Copy Markdown
Contributor

@fede-kamel fede-kamel commented May 30, 2026

Summary

Fixes #289. In Pydantic v2 SecretStr("") is falsy, so the truthy guard

if cfg.wallet_password:
    params["wallet_password"] = cfg.wallet_password.get_secret_value()

silently dropped an explicit wallet_password="" before it reached
oracledb.create_pool_async. But "" is python-oracledb's documented idiom for an
auto-login (cwallet.sso) wallet. With it dropped, the thin driver falls through to
the encrypted ewallet.pem path and fails at connect time with DPY-6005 /
OSError: [Errno 22] (and prompts for a PEM passphrase on a TTY).

Change

Switch the guard to is not None at all seven Oracle pool builders, so an omitted
password (None) is still skipped while an explicit "" is forwarded:

  • memory/backends/oracle.py
  • memory/backends/oracle_versioned.py
  • memory/store_backends/oracle.py
  • rag/embeddings/oracle_indb.py
  • rag/chunkers/oracle_indb.py
  • rag/stores/oracle.py
  • rag/loaders/oracle.py

Root-cause confirmation

from pydantic import SecretStr           # Pydantic 2.12
assert bool(SecretStr("")) is False        # truthy guard drops it
assert (SecretStr("") is not None) is True # `is not None` keeps it

Tests added

tests/unit/test_oracle_wallet_password_empty.py7 backends × 3 cases = 21 tests,
stubbing oracledb to capture the kwargs each _get_pool() sends to
create_pool_async:

  • empty-string "" → kwarg forwarded as ""
  • omitted (None) → kwarg absent
  • real value → forwarded unchanged

Testing performed

1. Unit

  • 21 new tests pass.
  • Existing Oracle unit suites pass alongside them (test_oracle_store,
    test_oracle_adb_loader, test_oracle_versioned_checkpointer,
    test_oracle_indb_embeddings, test_oracle_indb_chunker) — 143 tests total, no
    regressions.
  • Mutation check: temporarily restoring the truthy guard makes the matching test
    fail with AssertionError: empty-string wallet_password was dropped (truthy-guard regression), then passes again once the fix is restored — confirming the test
    actually pins the behavior.

2. No-database probe

Stubbing create_pool_async on the unpatched code shows the kwarg is dropped:

wallet_password forwarded? False
kwargs: ['config_dir', 'dsn', 'max', 'min', 'password', 'user', 'wallet_location']

With the fix, wallet_password is present.

3. Live Oracle Autonomous DB (auto-login wallet, wallet_password="")

Direct vs. Locus, same wallet + credentials:

Scenario path result
A — direct oracledb.create_pool_async(..., wallet_password="") kwarg forwarded connected, select 1 -> 1
B — Locus backend, wallet_password="" (unpatched) kwarg dropped DPY-6005 / OSError: [Errno 22] (after the driver prompted for a PEM passphrase, falling through to ewallet.pem)
C — Locus backend, wallet_password="" (patched) kwarg forwarded connected, select 1 -> 1

4. Integration suite — tests/integration/test_oracle_rag.py

Run against a live ADB with an auto-login wallet and ORACLE_WALLET_PASSWORD="" (the
default, i.e. the #289 trigger), exercising OracleVectorStore:

  • 6 passed, 1 skipped (the skip is test_oracle_cohere_embeddings — needs an OCI
    GenAI profile that wasn't configured in this run; unrelated to this change).
  • The 6 passing tests (connection, add/get, vector search, …) all connect with
    wallet_password="".
  • Causation proof: restoring the truthy guard in rag/stores/oracle.py and re-running
    test_oracle_connection reproduces the failure end-to-end —
    OSError: [Errno 22]DPY-6005 — and re-applying the fix returns it to green. This
    ties the integration pass directly to the fix.

Note: tests/integration/rag/test_oracle_adb_store.py was reviewed but is not relevant
here — its fixture defaults wallet_password to the DB password (never ""), so it does
not exercise the auto-login path.

A self-contained reproduction probe (no database required) is posted on #289.

…closes #289)

Pydantic v2 made SecretStr("") falsy, so the truthy guard
`if cfg.wallet_password:` silently dropped an explicit
wallet_password="" before it reached oracledb.create_pool_async.

But "" is python-oracledb's documented idiom for an auto-login
(cwallet.sso) wallet. Dropping it forces the driver onto the encrypted
ewallet.pem path, which fails at connect time with DPY-6005 /
OSError: [Errno 22] (and prompts for a PEM passphrase on a TTY).

Switch the guard to `is not None` at all seven Oracle pool builders so
an omitted password (None) is still skipped while an explicit "" is
forwarded:

  - memory/backends/oracle.py
  - memory/backends/oracle_versioned.py
  - memory/store_backends/oracle.py
  - rag/embeddings/oracle_indb.py
  - rag/chunkers/oracle_indb.py
  - rag/stores/oracle.py
  - rag/loaders/oracle.py

Add tests/unit/test_oracle_wallet_password_empty.py: 7 backends x 3
cases (empty-string forwarded / None omitted / real value forwarded),
stubbing oracledb to capture create_pool_async kwargs.

Signed-off-by: Federico Kamelhar <federico.kamelhar@oracle.com>
@fede-kamel fede-kamel force-pushed the fix/289-wallet-password-empty-string branch from f46793b to 0602655 Compare May 30, 2026 11:54
@fede-kamel fede-kamel merged commit 6772dd9 into main May 30, 2026
10 checks passed
@fede-kamel fede-kamel deleted the fix/289-wallet-password-empty-string branch May 30, 2026 11:57
fede-kamel added a commit that referenced this pull request May 30, 2026
…290) (#291)

Bumps locus-sdk to 0.2.0b25. Fixes a Pydantic v2 regression where an
explicit wallet_password="" (the python-oracledb auto-login / cwallet.sso
idiom) was silently dropped by a truthy SecretStr guard, forcing the
encrypted ewallet.pem path and failing at connect with DPY-6005 /
OSError: [Errno 22]. The guard is now `is not None` across all seven
Oracle pool builders (closes #289).

Signed-off-by: Federico Kamelhar <federico.kamelhar@oracle.com>
fede-kamel added a commit that referenced this pull request May 30, 2026
…oses #292) (#293)

* chore(release): v0.2.0b25 — Oracle auto-login wallet_password="" fix (#290)

Bumps locus-sdk to 0.2.0b25. Fixes a Pydantic v2 regression where an
explicit wallet_password="" (the python-oracledb auto-login / cwallet.sso
idiom) was silently dropped by a truthy SecretStr guard, forcing the
encrypted ewallet.pem path and failing at connect with DPY-6005 /
OSError: [Errno 22]. The guard is now `is not None` across all seven
Oracle pool builders (closes #289).

Signed-off-by: Federico Kamelhar <federico.kamelhar@oracle.com>

* fix(rag): make OCI embedding dimension + input_type deterministic (closes #292)

OCIEmbeddings.embed_query() hardcoded input_type="SEARCH_QUERY" (ignoring
config) and embed_documents() hardcoded "SEARCH_DOCUMENT"; embed_query also
carried a dead `original_type` local and a misleading "frozen config" comment.

More importantly, the real dimension-mismatch trigger behind the report is
Cohere v4's Matryoshka output_dimensions, which Locus never set. cohere.embed-
v4.0 returns exactly the requested size (256/512/1024/1536) and OCI's
server-side default (1536 today) applies otherwise — so a table indexed at one
output_dimensions and queried at another raises ORA-51803. input_type does NOT
change the output dimension (verified live: v4 returns 1536 for both
SEARCH_QUERY and SEARCH_DOCUMENT; v3 returns 1024 for both).

Changes:
- Add OCIEmbeddingConfig.output_dimensions (default None). Forwarded to
  EmbedTextDetails on every embed path via a shared _build_embed_details
  helper, and only when set, so non-Matryoshka models never see the field.
- config.dimension now prefers output_dimensions, so the vector column is
  sized to match the pinned embedding dimension.
- Add OCIEmbeddingConfig.query_input_type (default SEARCH_QUERY) and read
  input_type from config in embed_documents; removes the hardcodes and the
  dead/misleading code in embed_query.

Tests: query_input_type / input_type configurability, output_dimensions
omitted-by-default + forwarded on all three paths, and config.dimension
reflecting output_dimensions.

Signed-off-by: Federico Kamelhar <federico.kamelhar@oracle.com>

---------

Signed-off-by: Federico Kamelhar <federico.kamelhar@oracle.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

OCA Verified All contributors have signed the Oracle Contributor Agreement.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

OracleBackend silently drops wallet_password="", breaks auto-login wallets (Pydantic v2 SecretStr is falsy)

1 participant