# 22033 — invalid_sql_json_subscript

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

# 22033

## At a glance {#at-a-glance}
A SQL/JSON array subscript is invalid. Fixed jsonpath paths distinguish out-of-bounds, non-single-numeric, and integer-range variants.

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

| Field | Value |
| --- | --- |
| SQLSTATE | `22033` |
| Condition | `invalid_sql_json_subscript` |
| Status | `active` |
| Known present by | `12.0` |
| Locked snapshots | `12.22, 13.23, 14.24, 15.19, 16.15, 17.11, 18.6, 19beta3` |
| Macros | `ERRCODE_INVALID_SQL_JSON_SUBSCRIPT` |
| Aliases | `—` |

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

## Messages {#messages}
The fixed subscript guards use these primary texts:

| Guard | Primary |
| --- | --- |
| subscript is not one numeric item | `jsonpath array subscript is not a single numeric value` |
| numeric subscript outside int32 | `jsonpath array subscript is out of integer range` |
| strict array bound failure | `jsonpath array subscript is out of bounds` |

## Meaning {#meaning}
The jsonpath executor evaluates each subscript expression as a result list. `getArrayIndex` requires exactly one numeric scalar, truncates it to an integer, and reports 22033 when the result is not a single numeric item or cannot fit the integer range. The later array-bound guard reports the same code for a negative start, reversed range, or upper bound past the array in strict mode. Lax mode ignores that structural out-of-bounds error and clamps the range to the available array; it does not turn a non-numeric or overflowing subscript into a valid index.

## Diagnosis {#diagnosis}
Inspect the subscript expression’s cardinality and type before inspecting array length. A path that yields multiple items, a non-numeric value, or an integer overflow uses the conversion messages; a numeric index or range that violates strict array bounds uses the out-of-bounds message. Record whether the path is strict or lax, because lax structural handling can produce an empty or clamped result instead of this ERROR. A later no-item behavior is 22035 when its SQL/JSON operation chooses to raise it.

## Response {#response}
Make the subscript expression return one finite numeric value in the integer range, and keep strict-mode bounds within the target array with a non-reversed range. If lax clamping or an empty result is intended, confirm that the path mode and surrounding SQL/JSON behavior express that intent. If an ERROR occurred in an explicit transaction, roll back or roll back to the existing savepoint before retrying; autocommit can retry the corrected expression.

## Versions {#versions}
The locked catalogue records this condition from 12.0; the fixed jsonpath source paths here are PostgreSQL 18.6. No natural runtime observation is claimed for this page.

## Related {#related}
[`22034`](../22034/), [`22035`](../22035/)

## Sources {#sources}
Array-bound handling is [`src/backend/utils/adt/jsonpath_exec.c#L892-929`](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/utils/adt/jsonpath_exec.c#L892). Subscript cardinality, truncation, and integer conversion are [`#L3442-3477`](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/utils/adt/jsonpath_exec.c#L3442). The structured [evidence record](../data/evidence/22033.json) retains all three 22033 guard roles; no natural runtime was run.
