Skip to content

Python-to-rust conversion of integer raises an OverflowError instead of ValueError when value is out of bounds #5179

Open
@touilleMan

Description

@touilleMan

Bug Description

Currently having a PyO3 function that takes an integer raises a OverflowError when called from Python with a value out of bound.

According to Python documentation, the use of OverflowError for handling int seems like a odd choice:

Raised when the result of an arithmetic operation is too large to be represented. This cannot occur for integers (which would rather raise MemoryError than give up).

However, for historical reasons, OverflowError is sometimes raised for integers that are outside a required range. Because of the lack of standardization of floating-point exception handling in C, most floating-point operations are not checked.

On the other hand, it is clearly defined that ValueError is the way to go when passing an invalid value with right type (the current issue is literally the given example 😄 ):

Passing arguments of the wrong type (e.g. passing a list when an int is expected) should result in a TypeError, but passing arguments with the wrong value (e.g. a number outside expected boundaries) should result in a ValueError.

In practice this is footgun since 1. PyO3 documentation doesn't mention this behavior and 2. ValueError is the de-facto standard for this kind of behavior
This creates hidden bugs when implementing types in PyO3 that are then used in validation framework, typically Pydantic.

Currently avoiding this issue consists on either manually handling PyInt conversion in the Rust code, or manually handling OverflowError in the Python code. In both case this is error prone since forgetting to do it has no impact on the happy case...

Steps to Reproduce

use pyo3::prelude::*;

#[pyfunction]
fn foo(x: u64)  {
    x * 2
}
>>> import foomodule
>>> foomodule.foo(-1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OverflowError: can't convert negative int to unsigned

Backtrace

Your operating system and version

Pop!_OS 22.04 LTS

Your Python version (python --version)

Python 3.12

Your Rust version (rustc --version)

rustc 1.85.0 (4d91de4e4 2025-02-17)

Your PyO3 version

0.22.6 (but the code responsible for this is present in master)

How did you install python? Did you use a virtualenv?

poetry

Additional Info

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions