{"record":{"id":"7e4565a2c68abd6e","repo":"prestodb/presto","slug":"duplicate-parameter-name","errorCode":"DUPLICATE_PARAMETER_NAME","errorMessage":"Duplicate function parameter name: %s","messagePattern":"Duplicate function parameter name: (.+?)","errorType":"error_code","errorClass":"SemanticException","httpStatus":null,"severity":"error","filePath":"presto-main-base/src/main/java/com/facebook/presto/sql/analyzer/StatementAnalyzer.java","lineNumber":1172,"sourceCode":"            checkFunctionName(node, node.getFunctionName(), node.isTemporary());\n\n            // Check no replace with temporary functions\n            if (node.isTemporary() && node.isReplace()) {\n                throw new SemanticException(NOT_SUPPORTED, node, \"REPLACE is not supported for temporary functions\");\n            }\n\n            // Check parameter\n            List<String> duplicateParameters = node.getParameters().stream()\n                    .map(SqlParameterDeclaration::getName)\n                    .map(Identifier::getValue)\n                    .collect(groupingBy(Function.identity(), counting()))\n                    .entrySet()\n                    .stream()\n                    .filter(entry -> entry.getValue() > 1)\n                    .map(Entry::getKey)\n                    .collect(toImmutableList());\n            if (!duplicateParameters.isEmpty()) {\n                throw new SemanticException(DUPLICATE_PARAMETER_NAME, node, \"Duplicate function parameter name: %s\", Joiner.on(\", \").join(duplicateParameters));\n            }\n\n            // Check return type\n            Type returnType = functionAndTypeResolver.getType(parseTypeSignature(node.getReturnType()));\n            List<Field> fields = node.getParameters().stream()\n                    .map(parameter -> Field.newUnqualified(parameter.getName().getLocation(), parameter.getName().getValue(), functionAndTypeResolver.getType(parseTypeSignature(parameter.getType()))))\n                    .collect(toImmutableList());\n            Scope functionScope = Scope.builder()\n                    .withRelationType(RelationId.anonymous(), new RelationType(fields))\n                    .build();\n            if (node.getBody() instanceof Return) {\n                Expression returnExpression = ((Return) node.getBody()).getExpression();\n                Type bodyType = analyzeExpression(returnExpression, functionScope).getExpressionTypes().get(NodeRef.of(returnExpression));\n                if (!functionAndTypeResolver.canCoerce(bodyType, returnType)) {\n                    throw new SemanticException(TYPE_MISMATCH, node, \"Function implementation type '%s' does not match declared return type '%s'\", bodyType, returnType);\n                }\n\n                verifyNoAggregateWindowOrGroupingFunctions(analysis.getFunctionHandles(), functionAndTypeResolver, returnExpression, \"CREATE FUNCTION body\");","sourceCodeStart":1154,"sourceCodeEnd":1190,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-main-base/src/main/java/com/facebook/presto/sql/analyzer/StatementAnalyzer.java#L1154-L1190","documentation":"A CREATE FUNCTION statement declares two or more parameters with the same name. Parameter names must be unique within a function signature so calls can bind arguments unambiguously, so the analyzer raises DUPLICATE_PARAMETER_NAME listing all offending names.","triggerScenarios":"CREATE FUNCTION ... (x INTEGER, x VARCHAR) ... — duplicate identifiers collected from node.getParameters() produce a non-empty duplicateParameters list.","commonSituations":"Copy-paste of parameter declarations when extending a function's arity; renaming one parameter but forgetting the second occurrence; templated SQL generation that concatenates parameter lists with repeats.","solutions":["Rename one of the duplicate parameters in the function signature.","Remove the redundant parameter if it was accidentally duplicated.","Fix the SQL generator/template to deduplicate parameter names."],"exampleFix":"// before\nCREATE FUNCTION f(x INTEGER, x INTEGER) RETURNS INTEGER RETURN x;\n// after\nCREATE FUNCTION f(x INTEGER, y INTEGER) RETURNS INTEGER RETURN x + y;","handlingStrategy":"validation","validationCode":"Set<String> params = parseParameterNames(createFunctionSql);\nif (params.size() != parseParameterList(createFunctionSql).size()) {\n    throw new IllegalArgumentException(\"Duplicate function parameter names: \" + (listSize - params.size()));\n}","typeGuard":null,"tryCatchPattern":"try {\n    execute(sql);\n} catch (SemanticException e) {\n    if (e.getCode().name().equals(\"DUPLICATE_PARAMETER_NAME\")) {\n        log.error(\"Rename duplicated parameters reported: {}\", e.getErrorMessage());\n    }\n    throw e;\n}","preventionTips":["Define function signatures once in a shared spec and generate SQL from it.","Add a lint rule that parses parameter lists and rejects duplicates.","Use distinct, descriptive parameter names (e.g., start_date/end_date) instead of generic x/y reuse."],"tags":["presto","sql-functions","naming","semantic-analysis"],"backgroundTag":"duplicate-identifier","analyzedSha":"55bb57d202de3b926896fa966c2c4a44c779634e","analyzedAt":"2026-09-04T12:50:26.162Z","contentChangedAt":"2026-09-04T12:50:26.162Z","schemaVersion":2},"datasetVersion":"2026-09-11T21:17:09.523Z"}