{"record":{"id":"f159ef367616d776","repo":"OpenRefine/OpenRefine","slug":"parameter-index-out-of-bounds","errorCode":null,"errorMessage":"Parameter index out of bounds","messagePattern":"Parameter index out of bounds","errorType":"validation","errorClass":"IndexOutOfBoundsException","httpStatus":null,"severity":"error","filePath":"main/src/com/google/refine/commands/row/AddRowsCommand.java","lineNumber":80,"sourceCode":"            Project project = getProject(request);\n            List<Row> rows = getRowData(request);\n            int insertionIndex = getInsertionIndex(request, project);\n\n            AbstractOperation op = new RowAdditionOperation(rows, insertionIndex);\n            op.validate();\n            Process process = op.createProcess(project, new Properties());\n\n            performProcessAndRespond(request, response, project, process);\n        } catch (Exception e) {\n            respondException(response, e);\n        }\n    }\n\n    public int getInsertionIndex(HttpServletRequest request, Project project) {\n        String data = request.getParameter(INDEX_PARAMETER);\n        int index = Integer.parseInt(data);\n        if (index < 0 || index > project.rows.size()) {\n            throw new IndexOutOfBoundsException(\"Parameter \" + INDEX_PARAMETER + \" out of bounds\");\n        }\n        return index;\n    }\n\n    public List<Row> getRowData(HttpServletRequest request) throws Exception {\n        String[] data = request.getParameterValues(ROWS_PARAMETER);\n        if (data.length == 0) {\n            throw new IllegalArgumentException(\"Parameter \" + ROWS_PARAMETER + \" is empty\");\n        }\n        List<Row> rows = new ArrayList<>(data.length);\n        Pool pool = new Pool();\n        for (String rowStr : data) {\n            Row row = Row.load(rowStr, pool);\n            if (!Objects.equals(rowStr, \"{}\")) {\n                throw new IllegalArgumentException(\"Row is not empty\");\n            }\n            rows.add(row);\n        }","sourceCodeStart":62,"sourceCodeEnd":98,"githubUrl":"https://github.com/OpenRefine/OpenRefine/blob/a946177e049f3b0644261661db36cbb0c81ccf8a/main/src/com/google/refine/commands/row/AddRowsCommand.java#L62-L98","documentation":"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').","triggerScenarios":"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.","commonSituations":"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.","solutions":["Pass a valid index between 0 and project.rows.size() (inclusive of size to append at the end)","Omit or fetch the index fresh from the project right before the call so it reflects current row count","Use index=0 to insert at the top or index=<rowCount> to append; verify the row count via project data first","Fix the parameter name — it must be exactly 'index' (INDEX_PARAMETER); a missing parameter makes parseInt throw"],"exampleFix":"// before\naddRows(project, \"abc\", rows)   // non-numeric index\n// after\naddRows(project, String.valueOf(project.rows.size()), rows) // append at end","handlingStrategy":"validation","validationCode":"if (index === undefined || !Number.isInteger(Number(index)) || Number(index) < 0 || Number(index) > rowCount) throw new Error(`index must be an integer in [0, ${rowCount}]`);","typeGuard":null,"tryCatchPattern":"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; }","preventionTips":["Always use 0-based indexes; to append, pass exactly project.rows.size()","Re-fetch the current row count immediately before each add-rows call","Ensure the parameter is named 'index' and always present","Never compute the index from stale snapshots of the project"],"tags":["http-api","index","validation"],"backgroundTag":"index-out-of-bounds","analyzedSha":"a946177e049f3b0644261661db36cbb0c81ccf8a","analyzedAt":"2026-09-08T10:21:27.735Z","contentChangedAt":"2026-09-08T10:21:27.735Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}