How to fix 22016: invalid_argument_for_nth_value_function in PostgreSQL

PostgreSQLINTERMEDIATEMEDIUMUpdated Dec 29, 2025ยท 93 views

The NTH_VALUE window function received an invalid argument for the row position parameter. The second argument must be a positive integer greater than zero.

Quick fix

Fixes 22016

NTH_VALUE(expression, n) OVER (
  [PARTITION BY ...]
  ORDER BY ...
  [frame_clause]
)
  1. Verify the NTH_VALUE syntax in your query
  2. Ensure the row position is a positive integer
  3. Cast dynamic position arguments to integer
  4. Add appropriate frame specification
postgresql โ€” error
NTH_VALUE(expression, n) OVER (
[PARTITION BY ...]
ORDER BY ...
[frame_clause]
)
22016: invalid_argument_for_nth_value_function

What this error means

PostgreSQL error 22016 occurs when the NTH_VALUE window function is called with an invalid row position argument. The NTH_VALUE(expression, n) function requires the second parameter 'n' to be a positive integer (1, 2, 3, etc.). Common causes include passing zero, negative numbers, non-integer values, or incorrect data types for the position parameter.

Typical symptoms

  • Queries using NTH_VALUE fail with 22016 error
  • Window function calls with dynamic row position parameters fail
  • Error appears when using NTH_VALUE with calculated or conditional row numbers

Common causes

  1. The row position argument (second parameter) is zero or negative
  2. The position argument is a non-integer value (float, decimal, etc.)
  3. The position argument is NULL or an invalid type
  4. The expression is evaluated to an invalid type for the row position

How to fix "22016: invalid_argument_for_nth_value_function"

1Verify the NTH_VALUE syntax in your query

Check your query for the NTH_VALUE function call. The correct syntax is:

sql
NTH_VALUE(expression, n) OVER (
  [PARTITION BY ...]
  ORDER BY ...
  [frame_clause]
)

The second argument must be a positive integer that specifies which row to retrieve.

2Ensure the row position is a positive integer

Check that the second argument to NTH_VALUE is a positive integer (greater than 0). If you're using a calculated value or variable, ensure it's converted to an integer.

sql
-- Wrong: position is zero
SELECT NTH_VALUE(salary, 0) OVER (ORDER BY salary) FROM employees;

-- Correct: position is a positive integer
SELECT NTH_VALUE(salary, 2) OVER (ORDER BY salary) FROM employees;
3Cast dynamic position arguments to integer

If you're using a calculated or variable row position, explicitly cast it to an integer:

sql
-- If using a calculated position
SELECT NTH_VALUE(column_name, CAST(position_value AS INTEGER)) 
OVER (ORDER BY other_column) 
FROM table_name;

-- Or use ::integer shorthand
SELECT NTH_VALUE(column_name, position_value::integer) 
OVER (ORDER BY other_column) 
FROM table_name;
4Add appropriate frame specification

By default, PostgreSQL uses a frame that may not include the Nth row. Specify the frame explicitly to ensure the Nth row is included:

sql
SELECT 
  employee_id,
  salary,
  NTH_VALUE(salary, 2) OVER (
    ORDER BY salary DESC
    ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
  ) AS second_highest_salary
FROM employees;

The frame specification ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ensures all rows are considered.

5Handle NULL positions with validation

If the position comes from a nullable column or calculation, validate it before using:

sql
SELECT 
  product_id,
  price,
  CASE 
    WHEN position_value > 0 
    THEN NTH_VALUE(price, position_value::integer) OVER (ORDER BY price)
    ELSE NULL
  END AS nth_price
FROM products;

This prevents NULL or zero values from being passed to NTH_VALUE.

Advanced notes

The NTH_VALUE function only considers rows within the current window frame, not the entire partition. By default, the frame is RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW, which may cause the function to return NULL if the Nth row hasn't been reached yet. Always specify an explicit frame clause (ROWS or RANGE) for predictable behavior. If N is greater than the number of rows in the frame, NTH_VALUE returns NULL, which is expected behavior and not an error condition. PostgreSQL does not implement the RESPECT NULLS/IGNORE NULLS or FROM FIRST/FROM LAST options from the SQL standard.

Frequently asked questions

What does "22016" mean?
PostgreSQL error 22016 occurs when the NTH_VALUE window function is called with an invalid row position argument. ). Common causes include passing zero, negative numbers, non-integer values, or incorrect data types for the position parameter.
How do I fix "22016"?
The NTH_VALUE window function received an invalid argument for the row position parameter. The second argument must be a positive integer greater than zero.
What causes "22016"?
The row position argument (second parameter) is zero or negative The position argument is a non-integer value (float, decimal, etc.) The position argument is NULL or an invalid type
Is the "22016" error serious?
It is a medium-severity error โ€” more of a blocker than a risk. The steps above resolve it.

Official resources & further reading