1 . What versions are you using?
platform.platform: Linux-4.14.35-2047.501.2.el7uek.x86_64-x86_64-with-glibc2.2.5
sys.maxsize > 2**32: True
platform.python_version: 3.9.22
oracledb.version: 3.4.x (also reproduced on 3.0.0)
Oracle Database: 19c Enterprise Edition Release 19.15.0.0.0
Connection mode: Thin async, SYSDBA
2. Is it an error or a hang or a crash?
An unhandled exception that crashes the user's coroutine. The DDL itself succeeds on the database — the failure is purely client-side, in the response parser.
3. What error(s) or behavior you are seeing?
On 3.4.x:
AttributeError: 'NoneType' object has no attribute 'decode'
File ".../oracledb/cursor.py", line 1200, in execute
await self._impl.execute(self)
File "src/oracledb/impl/thin/cursor.pyx", line 392, in execute
File "src/oracledb/impl/thin/protocol.pyx", line 874, in _process_single_message
File "src/oracledb/impl/thin/protocol.pyx", line 875, in oracledb.thin_impl.BaseAsyncProtocol._process_single_message
File "src/oracledb/impl/thin/protocol.pyx", line 851, in _process_message
File "src/oracledb/impl/thin/messages/base.pyx", line 274, in _process_keyword_value_pairs
On 3.0.0 the same code path raised:
UnboundLocalError: local variable 'key_value' referenced before assignment
File "src/oracledb/impl/thin/messages.pyx", line 1134, in _process_return_parameters
The DDL that triggers it (intermittently — depends on what the server includes in TTC return parameters):
ALTER PLUGGABLE DATABASE <pdb_name> OPEN READ ONLY
ALTER PLUGGABLE DATABASE <pdb_name> OPEN READ WRITE -- on snapshot copies
ALTER PLUGGABLE DATABASE <pdb_name> CLOSE IMMEDIATE
After the exception the connection is left in an inconsistent state and cannot be reused.
Root cause (proposed)
In src/oracledb/impl/thin/messages/base.pyx::_process_keyword_value_pairs (3.4.x):
cdef int _process_keyword_value_pairs(self, ReadBuffer buf,
uint16_t num_pairs) except -1:
...
if keyword_num == TNS_KEYWORD_NUM_CURRENT_SCHEMA:
self.conn_impl._current_schema = text_value.decode() # <-- NoneType.decode()
elif keyword_num == TNS_KEYWORD_NUM_EDITION:
self.conn_impl._edition = text_value.decode()
elif keyword_num == TNS_KEYWORD_NUM_TRANSACTION_ID:
self._update_sessionless_txn_state(binary_value)
The same bug exists in the older _process_return_parameters (3.0.0) where key_value is assigned only inside if num_bytes > 0.
Suggested fix
if keyword_num == TNS_KEYWORD_NUM_CURRENT_SCHEMA:
if text_value is not None:
self.conn_impl._current_schema = text_value.decode()
elif keyword_num == TNS_KEYWORD_NUM_EDITION:
if text_value is not None:
self.conn_impl._edition = text_value.decode()
4. Does your application call init_oracle_client()?
No. Thin mode only, async.
5. Runnable script
import asyncio
import oracledb
DSN = "host:1521/CDB19C"
SYS_PASSWORD = "..."
PDB_NAME = "TESTPDB"
IMAGE_FILE = "/path/to/source.pdb"
async def main():
conn = await oracledb.connect_async(
user="sys",
password=SYS_PASSWORD,
dsn=DSN,
mode=oracledb.SYSDBA,
)
async with conn.cursor() as cursor:
await cursor.execute(
f"CREATE PLUGGABLE DATABASE {PDB_NAME} AS CLONE USING '{IMAGE_FILE}'"
)
await cursor.execute(f"ALTER PLUGGABLE DATABASE {PDB_NAME} OPEN READ WRITE")
await cursor.execute(f"ALTER PLUGGABLE DATABASE {PDB_NAME} CLOSE IMMEDIATE")
await cursor.execute(f"ALTER PLUGGABLE DATABASE {PDB_NAME} OPEN READ ONLY")
await cursor.execute(f"ALTER PLUGGABLE DATABASE {PDB_NAME} CLOSE IMMEDIATE")
await cursor.execute(f"DROP PLUGGABLE DATABASE {PDB_NAME} INCLUDING DATAFILES")
await conn.close()
asyncio.run(main())
The crash is intermittent across runs but consistently appears on a fraction of OPEN READ ONLY / OPEN READ WRITE operations on Oracle 19c with this driver in thin async SYSDBA mode. With a fresh database session and after enough PDB lifecycle iterations, every execution sequence eventually hits it.
1 . What versions are you using?
platform.platform: Linux-4.14.35-2047.501.2.el7uek.x86_64-x86_64-with-glibc2.2.5
sys.maxsize > 2**32: True
platform.python_version: 3.9.22
oracledb.version: 3.4.x (also reproduced on 3.0.0)
Oracle Database: 19c Enterprise Edition Release 19.15.0.0.0
Connection mode: Thin async, SYSDBA
2. Is it an error or a hang or a crash?
An unhandled exception that crashes the user's coroutine. The DDL itself succeeds on the database — the failure is purely client-side, in the response parser.
3. What error(s) or behavior you are seeing?
On 3.4.x:
On 3.0.0 the same code path raised:
The DDL that triggers it (intermittently — depends on what the server includes in TTC return parameters):
After the exception the connection is left in an inconsistent state and cannot be reused.
Root cause (proposed)
In
src/oracledb/impl/thin/messages/base.pyx::_process_keyword_value_pairs(3.4.x):The same bug exists in the older
_process_return_parameters(3.0.0) where key_value is assigned only inside if num_bytes > 0.Suggested fix
4. Does your application call init_oracle_client()?
No. Thin mode only, async.
5. Runnable script
The crash is intermittent across runs but consistently appears on a fraction of OPEN READ ONLY / OPEN READ WRITE operations on Oracle 19c with this driver in thin async SYSDBA mode. With a fresh database session and after enough PDB lifecycle iterations, every execution sequence eventually hits it.