Incident brief
nth_value argument must be positive
nth_value(expr, n) returns the value from the n-th row of the window frame and requires n to be a positive integer; zero or a negative position raises this data exception.
What lands in your log
ERROR: argument of nth_value must be greater than zero
In 10 seconds
- What triggers it
- Use nth_value(expr, n) OVER (...) with n set to zero or a negative value.
- Fix
- Pass a positive row position to nth_value().
- Proof
- Reproduced on PostgreSQL 18.4 → A single windowed SELECT reproduces SQLSTATE 22016; nth_value rejects the non-positive position.
Fix
What to do right now
Application-level steps for this error.
- Pass a positive row position to nth_value().
- Validate any dynamic position before the call so it is always 1 or greater.
-- nth_value positions are 1-based and must be positive.
SELECT nth_value(g, 1) OVER (ORDER BY g) FROM generate_series(1,3) g;For this error
See this error live on the server
Run these against the affected instance to confirm the diagnosis before you act.
nth_value argument must be positive (22016) is statement-local: PostgreSQL does not retain the rejected value after the statement ends. Capture the exact bound value and statement position in application/server logs, then run this targeted validation before retrying.
Validate nth_value position
Validate the specific value/shape that can raise this SQLSTATE.
SELECT nth, nth <= 0 AS would_raise_22016
FROM (VALUES (0)) v(nth);Why it happens
What PostgreSQL is telling you
The mechanism behind the error, grounded in the official manual, not paraphrased.
PostgreSQL 18 Documentation, Appendix A. PostgreSQL Error Codes (Table A.1, Class 22, Data Exception)
22016 → invalid_argument_for_nth_value_functionRead the full section on postgresql.org →
Calling nth_value with a non-positive position
nth_value positions are 1-based, so nth_value(expr, 0) raises 'argument of nth_value must be greater than zero'.The session continues normally
Because nth_value's argument check errors out as a standalone statement, session B needs no ROLLBACK before continuing.Reproduce & verify
A real, single-session PostgreSQL reproduction
A literal transcript of SQL run against a live PostgreSQL instance in an isolated lab. The commands below are exactly what was executed.
- 1Use nth_value(expr, n) OVER (...) with n set to zero or a negative value.
- 2PostgreSQL validates the row-position argument as the frame is evaluated.
- 3A non-positive n aborts the statement with SQLSTATE 22016.
A query pulled 'the n-th event in each session' where n came from a parameter, and a zero position aborted the window query.
-- The error is self-contained in one statement; no schema is required.
SELECT 'no schema needed' AS setup_note;SELECT nth_value(g, 0) OVER (ORDER BY g) FROM generate_series(1,3) g;SELECT 'ok' AS session_after_error;What PostgreSQL actually returned
setup_note
------------------
no schema needed
(1 row)ERROR: argument of nth_value must be greater than zero session_after_error
---------------------
ok
(1 row)The same query works once nth_value is given a positive position.
Without this
Before: a zero position aborts
With this, tested
After: nth_value(g, 1) returns the first value
- A second operational test: exact SQL, raw output, measured result, and engineer notes
Card required. Cancel before day 7 and you are not charged.
Connected
Everything this error touches
Every page this SQLSTATE connects to: the concept that explains it, the runbooks that fix it, the parameters you tune to prevent it, and the sibling errors it travels with. All real cross-references. Jump straight in, or open the full interactive map.
Verification
- Last verified
- 2026-07-24 (isolated lab, PostgreSQL 18.4)
- Verification scope
- Verified against PostgreSQL 18.4 in an isolated lab environment
- Audit status
- reviewed
Went further?
Pro unlocks the second lab proof
Free page stops the bleeding. Pro adds the operational test, SQLSTATE audit, and deeper evidence, same error, more certainty.