Repository navigation
Description
What happens?
In testing threading/free threading, I observed that the PyError is not cleared on a UBIGINT conversion failure. This occurred when testing test_all_types.py, but is masked by the test exit and GIL.
duckdb-python/src/duckdb_py/native/python_conversion.cpp
Lines 963 to 967 in c535a23
| if (conversion_target.id() == LogicalTypeId::UBIGINT) { | |
| throw InvalidInputException("Python Conversion Failure: Value out of range for type %s", | |
| conversion_target); | |
| } | |
| PyErr_Clear(); |
* The PyErr_Clear() at 967 is really just at the wrong location.
The specific fix is adding PyErr_Clear() here. But, this may be an issue in other locations, such as:
duckdb-python/src/duckdb_py/native/python_conversion.cpp
Lines 975 to 977 in c535a23
| } else if (value == -1 && PyErr_Occurred()) { | |
| throw InvalidInputException("An error occurred attempting to convert a python integer"); | |
| } else { |
To Reproduce
PyErr_Clear() should be called before throwing an exception, after a PyErr_Occurred.
I can work on a reproducer, if needed, but I'm not sure I'll be able to against a GIL-enabled build.
OS:
Linux
DuckDB Package Version:
1.4.0dev
Python Version:
3.14
Full Name:
Paul T
Affiliation:
Iqmo
What is the latest build you tested with? If possible, we recommend testing with the latest nightly build.
I have tested with a source build
Did you include all relevant data sets for reproducing the issue?
No - Other reason (please specify in the issue body)
Did you include all code required to reproduce the issue?
- Yes, I have
Did you include all relevant configuration to reproduce the issue?
- Yes, I have
Activity
Tishj commentedon Sep 18, 2025
I crafted a test to hit this path:
But I'm not sure why not clearing the error is a problem, can you expand on this test to show why it becomes a problem?
Tishj commentedon Sep 18, 2025
Also, if this is a problem, can't we handle it generically, in the exception translation logic?
Do a check for:
in here?
Tishj commentedon Sep 18, 2025
This looks like it should work:
Result for
PyErr_Occurredis the same, so this happens directly after, before pybind11 does anything with the PyErrReset PyErr before throwing (duckdb#69)