{"record":{"id":"19855db0c631170f","repo":"apache/cassandra","slug":"function-does-not-declare-an-argument-with-index","errorCode":null,"errorMessage":"Function does not declare an argument with index ${index}","messagePattern":"Function does not declare an argument with index (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/cql3/functions/UDFContextImpl.java","lineNumber":136,"sourceCode":"    {\n        if (!(dataType instanceof UserType))\n            throw new IllegalStateException(\"Function argument is not a UDT but a \" + dataType.getName());\n        UserType userType = (UserType) dataType;\n        return userType.newValue();\n    }\n\n    private static TupleValue newTupleValue(DataType dataType)\n    {\n        if (!(dataType instanceof TupleType))\n            throw new IllegalStateException(\"Function argument is not a tuple type but a \" + dataType.getName());\n        TupleType tupleType = (TupleType) dataType;\n        return tupleType.newValue();\n    }\n\n    private UDFDataType getArgumentTypeByIndex(int index)\n    {\n        if (index < 0 || index >= argTypes.size())\n            throw new IllegalArgumentException(\"Function does not declare an argument with index \" + index);\n        return argTypes.get(index);\n    }\n\n    private UDFDataType getArgumentTypeByName(String argName)\n    {\n        UDFDataType arg = byName.get(argName);\n        if (arg == null)\n            throw new IllegalArgumentException(\"Function does not declare an argument named '\" + argName + '\\'');\n        return arg;\n    }\n}\n","sourceCodeStart":118,"sourceCodeEnd":148,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/cql3/functions/UDFContextImpl.java#L118-L148","documentation":"getArgumentTypeByIndex validates that the requested index exists in the function's declared argument list; if the index is negative or >= the number of arguments, an IllegalArgumentException is thrown. It backs newArgUDTValue and newArgTupleValue in UDFContextImpl.","triggerScenarios":"Calling udfContext.newArgTupleValue(i) or newArgUDTValue(i) with an index outside [0, argCount) — e.g. index 3 in a 3-argument function, or a negative index.","commonSituations":"Off-by-one errors after changing the function's argument list; hard-coded indices that no longer match CREATE FUNCTION; loops using argCount instead of argCount-1.","solutions":["Use an index within 0..(number of declared arguments - 1)","Prefer the by-name variant (newArgUDTValue(\"arg_name\")) to avoid index drift when signatures change","Update the UDF code whenever the CREATE FUNCTION argument list changes"],"exampleFix":"// before (3-arg function)\nTupleValue tv = context.newArgTupleValue(3); // out of range\n// after\nTupleValue tv = context.newArgTupleValue(2); // last valid index","handlingStrategy":"validation","validationCode":"// Validate index against the declared argument count:\nif (index < 0 || index >= argTypes.size()) throw new IndexOutOfBoundsException(\"no arg at index \" + index);","typeGuard":"boolean hasArg(int i, int argCount) { return i >= 0 && i < argCount; }","tryCatchPattern":"try { TupleValue tv = ctx.newArgTupleValue(i); }\ncatch (IllegalArgumentException e) {\n  if (e.getMessage().contains(\"does not declare an argument\")) { /* clamp index or use by-name lookup */ }\n  else throw e;\n}","preventionTips":["Prefer by-name accessors (newArgTupleValue(\"name\")) over indices","Re-verify hard-coded indices whenever the function signature changes"],"tags":["udf","argument-index","bounds","state"],"backgroundTag":"index-out-of-range","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}