OpenAPI integer formats require symmetric boundary checks.
In OpenAPI 3.0 specification mappings, integers without an explicit format default to standard signed 32-bit integers (ranging from -2,147,483,648 to 2,147,483,647). When an IntegerField is configured with boundaries that exceed 32-bit signed storage, the generator must emit format: "int64" so API client generators and documentation accurately reflect the 64-bit integer type.
Django REST Framework’s AutoSchema field mapping handled values extending past the signed int32 upper bound (> 2,147,483,647), but failed to detect when a negative minimum value dropped below the signed int32 lower bound (< -2,147,483,648). PR #9989, authored by Zain Nadeem, resolved this discrepancy.
Upper-bound check existed without its lower-bound counterpart.
In rest_framework/schemas/openapi.py, the logic mapping serializers.IntegerField checked whether field.max_value or field.min_value exceeded 2147483647. However, no condition checked whether field.min_value was less than -2147483648.
As a result, a field like IntegerField(max_value=2147483648) correctly generated format: int64, while an equally oversized negative range like IntegerField(min_value=-2147483649) generated only "type": "integer" without format: int64.
min_value = -2147483649min < -2147483648 not checked → format omittedEnforce both signed 32-bit limits with integer coercion.
The patch adds the missing lower signed-int32 boundary check while preserving comparison-time int() coercion. During maintainer review, it was confirmed that field bounds can occasionally be configured as non-coerced strings or numbers, so keeping explicit int() coercion ensures safe comparison across all valid boundary inputs.
# Signed int32 limits: [-2147483648, 2147483647]
if (
field.max_value is not None and int(field.max_value) > 2147483647
or field.min_value is not None and (
int(field.min_value) > 2147483647 or int(field.min_value) < -2147483648
)
):
content["format"] = "int64"Precision schema metadata without runtime side effects.
This is a focused OpenAPI schema metadata fix. It does not alter serializer validation, runtime data parsing, BigIntegerField handling, or coerce_to_string options.
| Configured Field | Previous Schema | Fixed Schema |
|---|---|---|
IntegerField(min_value=-2147483649) | {"type": "integer", "minimum": -2147483649} | {"type": "integer", "minimum": -2147483649, "format": "int64"} |
IntegerField(min_value=-2147483648) | {"type": "integer", "minimum": -2147483648} | {"type": "integer", "minimum": -2147483648} (no format) |
IntegerField(max_value=2147483647) | {"type": "integer", "maximum": 2147483647} | {"type": "integer", "maximum": 2147483647} (no format) |
IntegerField(max_value=2147483648) | {"type": "integer", "maximum": 2147483648, "format": "int64"} | {"type": "integer", "maximum": 2147483648, "format": "int64"} |
IntegerField(min_value=2147483648) | {"type": "integer", "minimum": 2147483648, "format": "int64"} | {"type": "integer", "minimum": 2147483648, "format": "int64"} |
Exhaustive boundary regression test coverage.
Regression tests were added to tests/schemas/test_openapi.py under TestFieldMapping. The test cases verify that -2147483649 triggers format: int64, while boundary values -2147483648 and 2147483647 remain formatted as standard integers without format tags.
Focused field-mapping test execution passed with 7 passed and 23 subtests passed (pytest tests/schemas/test_openapi.py::TestFieldMapping). All 7 continuous integration checks passed on the PR.
Boundary logic must be tested symmetrically.
- When mapping typed primitives to specification formats, test both positive and negative overflow boundaries.
- Schema generators are contracts: omitting format metadata causes generated client SDKs to allocate undersized types.
- Maintain coercion guards on field properties to prevent unexpected type errors during schema export.
- Targeted metadata improvements preserve full backward compatibility for existing runtime pipelines.