{"record":{"id":"dbadf424af155154","repo":"apache/cassandra","slug":"not-masking-function-s-cannot-be-used-for-masking","errorCode":null,"errorMessage":"Not-masking function %s cannot be used for masking table columns","messagePattern":"Not-masking function (.+?) cannot be used for masking table columns","errorType":"validation","errorClass":"InvalidRequestException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/cql3/functions/masking/ColumnMask.java","lineNumber":253,"sourceCode":"\n        private ScalarFunction findMaskingFunction(String keyspace, String table, ColumnIdentifier column, AbstractType<?> type, UserFunctions functions)\n        {\n            List<AssignmentTestable> args = new ArrayList<>(rawPartialArguments.size() + 1);\n            args.add(type);\n            args.addAll(rawPartialArguments);\n\n            Function function = FunctionResolver.get(keyspace, name, args, keyspace, table, type, functions);\n\n            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)","sourceCodeStart":235,"sourceCodeEnd":271,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/cql3/functions/masking/ColumnMask.java#L235-L271","documentation":"ColumnMask.findMaskingFunction rejects resolved native functions that are not instances of MaskingFunction. Only the built-in masking functions (mask_null, mask_default, mask_inner, mask_outer, hash) may be attached to columns; other native scalars like now(), toTimestamp(), or uuid() are disallowed.","triggerScenarios":"MASKED WITH now() or any non-masking native function in CREATE TABLE / ALTER TABLE masked-column DDL.","commonSituations":"Developer tries to use an ordinary native scalar function as a masker, unaware that the whitelist is limited to MaskingFunction implementations (plus user-defined functions in the table's keyspace).","solutions":["Use one of the built-in masking functions: mask_null, mask_default, mask_inner, mask_outer, or hash.","Create a scalar UDF in the same keyspace as the table and reference that instead."],"exampleFix":"// before\nALTER TABLE users ALTER created_at MASKED WITH now();\n// after\nALTER TABLE users ALTER created_at MASKED WITH mask_default(timestamp);","handlingStrategy":"validation","validationCode":"Set<String> nativeMasks = Set.of(\"mask_null\",\"mask_default\",\"mask_inner\",\"mask_outer\",\"hash\");\nif (fnKeyspace == null && !nativeMasks.contains(fnName.toLowerCase()))\n  throw new IllegalArgumentException(fnName + \" is not a masking function\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat the built-in masking function names as an exhaustive whitelist.","Prefer UDFs for anything custom rather than repurposing native scalar functions."],"tags":["cql","masking","native-function","unsupported-operation"],"backgroundTag":"unsupported-operation","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"}