prestodb/presto · error · PrestoException
FUNCTION_IMPLEMENTATION_ERROR
FUNCTION_IMPLEMENTATION_ERROR
Error message
When function got no input, it should either produce output or return Blocked state
What it means
FUNCTION_IMPLEMENTATION_ERROR raised by RegularTableFunctionPartition.process when a table function implementation neither produced an output page nor declared itself Blocked despite receiving no input data in this round. Table functions follow a WorkProcessor protocol: each step must yield a result, be blocked, or have consumed input; producing neither violates the contract. This is a bug in the table function's implementation, not user SQL.
Source
Thrown at presto-main-base/src/main/java/com/facebook/presto/operator/RegularTableFunctionPartition.java:139
public WorkProcessor.ProcessState<Page> process()
{
TableFunctionProcessorState state = tableFunction.process(inputPages);
boolean functionGotNoData = inputPages == null;
if (state == FINISHED) {
return WorkProcessor.ProcessState.finished();
}
if (state instanceof TableFunctionProcessorState.Blocked) {
return WorkProcessor.ProcessState.blocked(toListenableFuture(((TableFunctionProcessorState.Blocked) state).getFuture()));
}
TableFunctionProcessorState.Processed processed = (TableFunctionProcessorState.Processed) state;
if (processed.isUsedInput()) {
inputPages = prepareInputPages();
}
if (processed.getResult() != null) {
return WorkProcessor.ProcessState.ofResult(appendPassThroughColumns(processed.getResult()));
}
if (functionGotNoData) {
throw new PrestoException(FUNCTION_IMPLEMENTATION_ERROR, "When function got no input, it should either produce output or return Blocked state");
}
return WorkProcessor.ProcessState.blocked(immediateFuture(null));
}
});
}
/**
* Iterate over the partition by page and extract pages for each table function source from the input page.
* For each source, project the columns required by the table function.
* If for some source all data in the partition has been consumed, Optional.empty() is returned for that source.
* It happens when the partition of this source is shorter than the partition of some other source.
* The overall length of the table function partition is equal to the length of the longest source partition.
* When all sources are fully consumed, this method returns null.
* <p>
* NOTE: There are two types of table function's source semantics: set and row. The two types of sources should be handled
* by the TableFunctionDataProcessor in different ways. For a source with set semantics, the whole partition can be used for computations,
* while for a source with row semantics, each row should be processed independently from all other rows.
* To enforce that behavior, we could pass to the TableFunctionDataProcessor only one row from a table with row semantics.View on GitHub (pinned to 55bb57d202)
Solutions
- Fix the table function implementation so that when no input is present it either produces a result page or returns a blocked state.
- Check the processor's contract handling of empty input partitions (set vs rows source semantics).
- If using a built-in function, reproduce with a minimal query and file a bug with the function name and plan.
- Verify the state machine transitions in processOperator/processed handling conform to WorkProcessor.ProcessState expectations.
Example fix
// before (custom table function)
if (state.isFinished()) { return ProcessState.finished(); }
// never yields result or blocked on empty input
// after
if (state.isFinished()) { return ProcessState.finished(); }
if (noInputProcessed && state.getResult() == null) {
return ProcessState.blocked(immediateFuture(null));
} Defensive patterns
Strategy: try-catch
Validate before calling
// When authoring a table function, unit-test the empty-input path:
@Test
void emptyPartitionMustBlockOrEmit() {
var state = processor.process(emptyInput);
assertTrue(state.getResult() != null || state.isBlocked(),
"function with no input must produce output or be blocked");
} Try / catch
try {
functionOutput = executeTableFunctionQuery();
} catch (PrestoException e) {
if ("FUNCTION_IMPLEMENTATION_ERROR".equals(e.getErrorCode().getName())
&& e.getMessage().contains("no input")) {
throw new IllegalStateException("table function bug; report to function author", e);
}
throw e;
} Prevention
- Test custom table functions with empty partitions and single-row inputs
- Follow the WorkProcessor state contract strictly: result, blocked, or finished each step
- Keep processor state-machine handling up to date when upgrading Presto
- Report built-in function hits upstream with a minimal repro
When it happens
Trigger: The function's processor (TableFunctionProcessorState) reports processed data but getResult() is null and functionGotNoData is true — i.e. the processor neither returned a page nor a blocked continuation while no input rows were supplied.
Common situations: Developing a custom TableFunctionDataProcessor that returns finished/processed states inconsistently; changing partitioning or pass-through semantics so the function is invoked with empty partitions; upgrading Presto where the processor state contract became stricter.
Related errors
- ALREADY_EXISTS
- FUNCTION_NOT_FOUND
- FUNCTION_IMPLEMENTATION_ERROR
- INVALID_FUNCTION_ARGUMENT
- INVALID_FUNCTION_ARGUMENT
AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04).
Data as JSON: /api/errors/5c40e706ccee4cb9.
Report an issue: GitHub.