# 22003 — numeric_value_out_of_range

> Source-backed reference for PostgreSQL SQLSTATE 22003.
---

# 22003

## At a glance {#at-a-glance}

22003 is `numeric_value_out_of_range`. Fixed paths cover integer conversion, numeric overflow, and subsystem-specific range checks; the page centers on numeric conversion and preserves those boundaries.

<!-- BEGIN SQLSTATE FACTS: generated by scripts/generate.py; do not edit -->

| Field | Value |
| --- | --- |
| SQLSTATE | `22003` |
| Condition | `numeric_value_out_of_range` |
| Status | `active` |
| Known present by | `7.4` |
| Locked snapshots | `9.0.23, 9.1.24, 9.2.24, 9.3.25, 9.4.26, 9.5.25, 9.6.24, 10.23, 11.22, 12.22, 13.23, 14.24, 15.19, 16.15, 17.11, 18.6, 19beta3` |
| Macros | `ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE` |
| Aliases | `—` |

<!-- source facts: data/errcodes/22003.json -->
<!-- END SQLSTATE FACTS -->

The shared case casts `2147483648` to `integer` to capture the range error, then casts `2147483647` as the representable repair. Send the two SELECT statements separately; the first is expected to fail before the repair expression runs. The runner controls the session and cleanup; no schema setup is required.

<!-- BEGIN SQLSTATE SNIPPET: integer_out_of_range -->
```sql
SELECT '2147483648'::integer;
SELECT '2147483647'::integer;
```
<!-- END SQLSTATE SNIPPET -->

Calibration observed integer input `2147483648` rejected with `value "2147483648" is out of range for type integer`; `2147483647` succeeded. The PostgreSQL 18.6 path used `pg_strtoint32_safe`, while the REL_10_23 source path used `pg_atoi`; both runner autocommit sessions returned to `IDLE`.

## Messages {#messages}

The fixed integer input guard raises `ERROR` with primary `value "%s" is out of range for type %s`. Other confirmed source paths use `value overflows numeric format` (numeric factorial) and `integer out of range` (`width_bucket`'s result conversion). These groups have no separate DETAIL or HINT in the cited source. The selected runtime observed only the integer-input template.

## Meaning {#meaning}

`22003` covers a numeric or range contract that the selected operation cannot represent. The fixed catalogue member is used by integer conversion, exact-numeric overflow, and subsystem checks; representative messages include `integer out of range` and `value overflows numeric format`. Other source paths may use the same SQLSTATE with a different message, so the SQLSTATE alone is not a type diagnosis.

## Diagnosis {#diagnosis}

Read the primary message and source object first. The observed `integer` case proves only an int4 input-conversion boundary; it does not characterize every numeric expression. For an integer conversion, identify the source and target integer widths and whether the failure occurred during input, assignment, cast, arithmetic, or an extension function. For `numeric`, distinguish declared precision/scale from arithmetic overflow and preserve the operands and rounding mode. A value can be syntactically valid and still be outside the target range.

## Response {#response}

Validate the range before the conversion and choose a representation that matches the business contract: reject the value, rescale it explicitly, or use a wider supported type. For arithmetic, inspect intermediate results rather than only the final column. For a subsystem-specific message, repair the named subsystem. The frozen case used autocommit, so the failed cast left the session `IDLE`; inside an explicit transaction, roll back the transaction or roll back to a pre-existing savepoint before retrying the corrected expression. Do not blanket-retry a deterministic range failure or silently clamp money, identifiers, or counters.

## Versions {#versions}

The locked catalogue records this condition from 7.4 in the listed formal snapshots and 19beta3; fixed source coverage is PostgreSQL 18.6.

## Related {#related}

[`22001`](../22001/) for string length, [`22007`](../22007/) for datetime format, and [`22008`](../22008/) for datetime field/range overflow.

## Sources {#sources}

Representative fixed paths include integer input in [`numutils.c#L603-L612`](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/utils/adt/numutils.c#L603-L612), numeric overflow in [`numeric.c#L3765-L3769`](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/utils/adt/numeric.c#L3765-L3769), and the `width_bucket` result conversion in [`numeric.c#L2042-L2046`](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/utils/adt/numeric.c#L2042-L2046). The structured [evidence record](../data/evidence/22003.json) records the fixed message families and source hashes.
