apache/cassandra · error · InvalidRequestException
Function ' ' must have directive
Error message
Function '%s' must have %s directive
What it means
When OR REPLACE replaces an existing UDF, Cassandra requires the null-input behavior directive to match: a replacement declared CALLED ON NULL INPUT cannot replace one declared RETURNS NULL ON NULL INPUT, and vice versa. The statement compares calledOnNullInput against the existing UDFunction's flag and throws when they differ.
Solutions
- Match the existing directive in the OR REPLACE statement
- Drop and recreate the function if the null-input semantics must genuinely change
- Query system_schema.functions to check the existing function's called_on_null_input flag first
Example fix
// before CREATE OR REPLACE FUNCTION ks.f(int) CALLED ON NULL INPUT RETURNS int ... -- existing is RETURNS NULL ON NULL INPUT // after CREATE OR REPLACE FUNCTION ks.f(int) RETURNS NULL ON NULL INPUT RETURNS int ...
Defensive patterns
Strategy: validation
Validate before calling
ResultSet rs = session.execute("SELECT called_on_null_input FROM system_schema.functions WHERE keyspace_name = ? AND function_name = ?", ks, fn);
boolean existing = rs.all().get(0).getBool(0);
if (existing != newCalledOnNullInput) throw new IllegalStateException("Directive mismatch for " + fn); Try / catch
try { session.execute(stmt); } catch (InvalidRequestException e) { if (e.getMessage().contains("must have")) { /* align CALLED/RETURNS ON NULL INPUT directive */ } else throw e; } Prevention
- Look up called_on_null_input before OR REPLACE
- Keep the null-input directive stable across function versions
- To change semantics, drop and recreate explicitly
When it happens
Trigger: CREATE OR REPLACE FUNCTION where the new declaration's CALLED ON NULL INPUT / RETURNS NULL ON NULL INPUT directive differs from the existing function's directive.
Common situations: Changing a function's null-handling semantics during an update; copying a function body but altering the directive; schema generated by tools that default the directive differently.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- Cannot replace function
- Argument ' ' cannot be frozen; remove frozen<> modifier from
- Argument ' ' cannot be frozen; remove frozen<> modifier from
- 'DROP FUNCTION ' matches multiple function definitions…
- Duplicate argument names for given function
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/881ea05d8bbac08e.
Report an issue: GitHub.
Appendix: source
Thrown at src/java/org/apache/cassandra/cql3/statements/schema/CreateFunctionStatement.java:150
calledOnNullInput,
language,
body);
UserFunction existingFunction = keyspace.userFunctions.find(function.name(), argumentTypes).orElse(null);
if (null != existingFunction)
{
if (existingFunction.isAggregate())
throw ire("Function '%s' cannot replace an aggregate", functionName);
if (ifNotExists)
return schema;
if (!orReplace)
throw ire("Function '%s' already exists", functionName);
if (calledOnNullInput != ((UDFunction) existingFunction).isCalledOnNullInput())
{
throw ire("Function '%s' must have %s directive",
functionName,
calledOnNullInput ? "CALLED ON NULL INPUT" : "RETURNS NULL ON NULL INPUT");
}
if (!returnType.isCompatibleWith(existingFunction.returnType()))
{
throw ire("Cannot replace function '%s', the new return type %s is not compatible with the return type %s of existing function",
functionName,
returnType.asCQL3Type(),
existingFunction.returnType().asCQL3Type());
}
// TODO: update dependent aggregates
}
return schema.withAddedOrUpdated(keyspace.withSwapped(keyspace.userFunctions.withAddedOrUpdated(function)));
}
View on GitHub (pinned to 88fd0f6a0e)