{"record":{"id":"ed1f67e39ea4e065","repo":"apache/cassandra","slug":"masking-function-s-return-type-is-s-this-is-dif","errorCode":null,"errorMessage":"Masking function %s return type is %s. This is different to the type of the masked column %s of type %s. Masking functions can only be attached to table columns if they return the same data type as the masked column.","messagePattern":"Masking function (.+?) return type is (.+?)\\. This is different to the type of the masked column (.+?) of type (.+?)\\. Masking functions can only be attached to table columns if they return the same data type as the masked column\\.","errorType":"validation","errorClass":"InvalidRequestException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/cql3/functions/masking/ColumnMask.java","lineNumber":262,"sourceCode":"            if (function == null)\n                throw invalidRequest(\"Unable to find masking function for %s, \" +\n                                     \"no declared function matches the signature %s\",\n                                     column, this);\n\n            if (function.isAggregate())\n                throw invalidRequest(\"Aggregate function %s cannot be used for masking table columns\", this);\n\n            if (function.isNative() && !(function instanceof MaskingFunction))\n                throw invalidRequest(\"Not-masking function %s cannot be used for masking table columns\", this);\n\n            if (!function.isNative() && !function.name().keyspace.equals(keyspace))\n                throw invalidRequest(\"Masking function %s doesn't belong to the same keyspace as the table %s.%s\",\n                                     this, keyspace, table);\n\n            CQL3Type returnType = function.returnType().asCQL3Type();\n            CQL3Type expectedType = type.asCQL3Type();\n            if (!returnType.equals(expectedType))\n                throw invalidRequest(\"Masking function %s return type is %s. \" +\n                                     \"This is different to the type of the masked column %s of type %s. \" +\n                                     \"Masking functions can only be attached to table columns \" +\n                                     \"if they return the same data type as the masked column.\",\n                                     this, returnType, column, expectedType);\n\n            return (ScalarFunction) function;\n        }\n\n        private ByteBuffer[] preparePartialArguments(String keyspace, ScalarFunction function)\n        {\n            // Note that there could be null arguments\n            ByteBuffer[] arguments = new ByteBuffer[rawPartialArguments.size()];\n\n            for (int i = 0; i < rawPartialArguments.size(); i++)\n            {\n                String term = rawPartialArguments.get(i).toString();\n                AbstractType<?> type = function.argTypes().get(i + 1);\n                arguments[i] = Term.asBytes(keyspace, term, type);","sourceCodeStart":244,"sourceCodeEnd":280,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/cql3/functions/masking/ColumnMask.java#L244-L280","documentation":"ColumnMask.findMaskingFunction enforces that the masking function's return type exactly equals the type of the column being masked. Because the masked value replaces the column value in results, a type-changing mask would break type expectations, so mismatched signatures are rejected.","triggerScenarios":"MASKED WITH a function whose return type differs from the column type, e.g. col is int but the function returns text, or a hash masking function applied to a non-blob column without matching signature.","commonSituations":"Applying mask_inner(text,...) to an int column, writing a UDF returning text to mask a bigint column, or after a column type migration the previously valid mask no longer matches.","solutions":["Pick/adjust the masking function so its return type matches the column type exactly (compare CQL3Type).","For UDFs, add a returns-clause overload matching the column type or create a new function with the correct return type.","If the column type is wrong for your purpose, ALTER the column semantics first (note Cassandra restricts type changes)."],"exampleFix":"// before\nALTER TABLE users ALTER email MASKED WITH hash(text); // hash(blob) vs text column\n// after\nALTER TABLE users ALTER email MASKED WITH mask_inner(text, 1, 3, 'x');","handlingStrategy":"validation","validationCode":"// verify return type matches column type before DDL\nRow r = session.execute(\"SELECT argument_types, return_type FROM system_schema.functions WHERE keyspace_name=? AND function_name=?\", ks, fn).one();\nif (r != null && !r.getString(\"return_type\").equals(columnType))\n  throw new IllegalArgumentException(\"return type \" + r.getString(\"return_type\") + \" != column type \" + columnType);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Map each column type to a masking function of identical return type in your schema conventions doc.","Re-check masking policies after any column type change."],"tags":["cql","masking","type-mismatch","return-type"],"backgroundTag":"type-mismatch","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"}