{"record":{"id":"5abbf1ceef0c19e1","repo":"prestodb/presto","slug":"invalid-function-argument-5abbf1","errorCode":"INVALID_FUNCTION_ARGUMENT","errorMessage":"the size of fromType and toType must match","messagePattern":"the size of fromType and toType must match","errorType":"error_code","errorClass":"PrestoException","httpStatus":null,"severity":"error","filePath":"presto-main-base/src/main/java/com/facebook/presto/operator/scalar/RowToRowCast.java","lineNumber":86,"sourceCode":"\npublic class RowToRowCast\n        extends SqlOperator\n{\n    public static final RowToRowCast ROW_TO_ROW_CAST = new RowToRowCast();\n\n    private RowToRowCast()\n    {\n        super(CAST, ImmutableList.of(withVariadicBound(\"F\", \"row\"), withVariadicBound(\"T\", \"row\")), ImmutableList.of(), parseTypeSignature(\"T\"), ImmutableList.of(parseTypeSignature(\"F\")));\n    }\n\n    @Override\n    public BuiltInScalarFunctionImplementation specialize(BoundVariables boundVariables, int arity, FunctionAndTypeManager functionAndTypeManager)\n    {\n        checkArgument(arity == 1, \"Expected arity to be 1\");\n        Type fromType = boundVariables.getTypeVariable(\"F\");\n        Type toType = boundVariables.getTypeVariable(\"T\");\n        if (fromType.getTypeParameters().size() != toType.getTypeParameters().size()) {\n            throw new PrestoException(StandardErrorCode.INVALID_FUNCTION_ARGUMENT, \"the size of fromType and toType must match\");\n        }\n        Class<?> castOperatorClass = generateRowCast(fromType, toType, functionAndTypeManager);\n        MethodHandle methodHandle = methodHandle(castOperatorClass, \"castRow\", SqlFunctionProperties.class, Block.class);\n        return new BuiltInScalarFunctionImplementation(\n                false,\n                ImmutableList.of(valueTypeArgumentProperty(RETURN_NULL_ON_NULL)),\n                methodHandle);\n    }\n\n    private static Class<?> generateRowCast(Type fromType, Type toType, FunctionAndTypeManager functionAndTypeManager)\n    {\n        List<Type> toTypes = toType.getTypeParameters();\n        List<Type> fromTypes = fromType.getTypeParameters();\n\n        CallSiteBinder binder = new CallSiteBinder();\n\n        // Embed the SHA256 hash code of input and output types into the generated class name instead of the raw type names,\n        // which could prevent the class name from hitting the length limitation and invalid characters.","sourceCodeStart":68,"sourceCodeEnd":104,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-main-base/src/main/java/com/facebook/presto/operator/scalar/RowToRowCast.java#L68-L104","documentation":"RowToRowCast specializes the ROW(F...) -> ROW(T...) cast. The generated row cast requires source and target rows to have the same number of fields; when the type variables have differing field counts it throws INVALID_FUNCTION_ARGUMENT, since a cast between different-arity rows cannot be generated.","triggerScenarios":"Executing CAST(row_value AS ROW(a, b)) where row_value's row type has a different number of fields than the target (e.g. casting ROW(1,2,3) to ROW(x INT, y INT)).","commonSituations":"Schema drift: an upstream table's row column gained/lost a field while downstream casts still assume the old arity; hand-written casts omitting a field.","solutions":["Make the CAST target row type have the same number of fields as the source (add or remove fields to match).","Rebuild the row explicitly: use row field access (r[1], r[2], ...) and construct a new row of the desired arity.","Fix upstream schema so row arity is stable, or version the row type.","Use try_cast to get NULL instead of failing while migrating."],"exampleFix":"-- before\nSELECT CAST(r AS ROW(a INTEGER, b INTEGER)); -- r is ROW(x,y,z)\n-- after\nSELECT CAST(ROW(r[1], r[2]) AS ROW(a INTEGER, b INTEGER));","handlingStrategy":"type-guard","validationCode":"WHERE cardinality(typehints(fromType)) = cardinality(typehints(toType)) -- ensure same field count before CAST","typeGuard":null,"tryCatchPattern":"SELECT try_cast(r AS ROW(a INTEGER, b INTEGER)) AS r2;","preventionTips":[],"tags":["presto","sql","cast","row-type","arity"],"backgroundTag":"row-type-cast-mismatch","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"}