OpenRefine/OpenRefine · error · IndexOutOfBoundsException

Parameter index out of bounds

Error message

Parameter index out of bounds

What it means

AddRowsCommand.getInsertionIndex parses the 'index' request parameter and validates that it falls within [0, project.rows.size()]. If the parameter is missing, non-numeric, or outside the valid insertion range, the command throws IndexOutOfBoundsException('Parameter index out of bounds').

Solutions

  1. Pass a valid index between 0 and project.rows.size() (inclusive of size to append at the end)
  2. Omit or fetch the index fresh from the project right before the call so it reflects current row count
  3. Use index=0 to insert at the top or index=<rowCount> to append; verify the row count via project data first
  4. Fix the parameter name — it must be exactly 'index' (INDEX_PARAMETER); a missing parameter makes parseInt throw

Example fix

// before
addRows(project, "abc", rows)   // non-numeric index
// after
addRows(project, String.valueOf(project.rows.size()), rows) // append at end
Defensive patterns

Strategy: validation

Validate before calling

if (index === undefined || !Number.isInteger(Number(index)) || Number(index) < 0 || Number(index) > rowCount) throw new Error(`index must be an integer in [0, ${rowCount}]`);

Try / catch

try { addRows(project, index, rows); } catch (IndexOutOfBoundsException e) { if (e.getMessage().contains("Parameter index out of bounds")) { index = project.rows.size(); /* append instead */ } else throw e; }

Prevention

When it happens

Trigger: POSTing to /command/core/add-rows with an index parameter that is negative, greater than the number of existing rows, absent (NumberFormatException on parseInt of null), or non-numeric text.

Common situations: Automation scripts computing the row index from stale project state after rows were deleted; passing 1-based indexes where 0-based is expected; forgetting the index parameter entirely in API calls.

Related errors


AI-assisted analysis of OpenRefine/OpenRefine@a946177e04 (2026-09-08). Data as JSON: /api/errors/f159ef367616d776. Report an issue: GitHub.

Appendix: source

Thrown at main/src/com/google/refine/commands/row/AddRowsCommand.java:80

            Project project = getProject(request);
            List<Row> rows = getRowData(request);
            int insertionIndex = getInsertionIndex(request, project);

            AbstractOperation op = new RowAdditionOperation(rows, insertionIndex);
            op.validate();
            Process process = op.createProcess(project, new Properties());

            performProcessAndRespond(request, response, project, process);
        } catch (Exception e) {
            respondException(response, e);
        }
    }

    public int getInsertionIndex(HttpServletRequest request, Project project) {
        String data = request.getParameter(INDEX_PARAMETER);
        int index = Integer.parseInt(data);
        if (index < 0 || index > project.rows.size()) {
            throw new IndexOutOfBoundsException("Parameter " + INDEX_PARAMETER + " out of bounds");
        }
        return index;
    }

    public List<Row> getRowData(HttpServletRequest request) throws Exception {
        String[] data = request.getParameterValues(ROWS_PARAMETER);
        if (data.length == 0) {
            throw new IllegalArgumentException("Parameter " + ROWS_PARAMETER + " is empty");
        }
        List<Row> rows = new ArrayList<>(data.length);
        Pool pool = new Pool();
        for (String rowStr : data) {
            Row row = Row.load(rowStr, pool);
            if (!Objects.equals(rowStr, "{}")) {
                throw new IllegalArgumentException("Row is not empty");
            }
            rows.add(row);
        }

View on GitHub (pinned to a946177e04)