apache/iceberg · error · FunctionNotExistException

FunctionNotExistException

Error message

FunctionNotExistException

What it means

FlinkCatalog registers no functions, so getFunction always throws FunctionNotExistException for any function path. This mirrors the catalog contract: functionExists returns false and listFunctions returns empty. The exception signals the function namespace is entirely unimplemented for Iceberg catalogs.

Source

Thrown at flink/v2.3/flink/src/main/java/org/apache/iceberg/flink/FlinkCatalog.java:750

  @Override
  public void alterPartition(
      ObjectPath tablePath,
      CatalogPartitionSpec partitionSpec,
      CatalogPartition newPartition,
      boolean ignoreIfNotExists)
      throws CatalogException {
    throw new UnsupportedOperationException();
  }

  @Override
  public List<String> listFunctions(String dbName) throws CatalogException {
    return Collections.emptyList();
  }

  @Override
  public CatalogFunction getFunction(ObjectPath functionPath)
      throws FunctionNotExistException, CatalogException {
    throw new FunctionNotExistException(getName(), functionPath);
  }

  @Override
  public boolean functionExists(ObjectPath functionPath) throws CatalogException {
    return false;
  }

  @Override
  public void createFunction(
      ObjectPath functionPath, CatalogFunction function, boolean ignoreIfExists)
      throws CatalogException {
    throw new UnsupportedOperationException();
  }

  @Override
  public void alterFunction(
      ObjectPath functionPath, CatalogFunction newFunction, boolean ignoreIfNotExists)
      throws CatalogException {

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Use Flink's built-in functions or declare UDFs as temporary/system functions in the job (TableEnvironment.createTemporarySystemFunction) instead of catalog functions.
  2. If code may call getFunction, catch FunctionNotExistException and fall back to temporary function resolution.
  3. Register Iceberg transformations in SQL via temporary functions or views, not persistent catalog functions.

Example fix

// before
CatalogFunction f = catalog.getFunction(new ObjectPath(db, "my_udf"));
// after
try {
  CatalogFunction f = catalog.getFunction(functionPath);
} catch (FunctionNotExistException e) {
  tableEnv.createTemporarySystemFunction("my_udf", MyUdf.class);
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (catalog instanceof FlinkCatalog) {
  // no catalog functions exist; resolve UDFs via TableEnvironment instead
}

Type guard

boolean supportsFunctions = !(catalog instanceof FlinkCatalog);

Try / catch

try {
  fn = catalog.getFunction(functionPath);
} catch (FunctionNotExistException e) {
  fn = tableEnv.getTemporarySystemFunction(functionPath.getObjectName())
      .orElseThrow(() -> new IllegalStateException("Function not registered: " + functionPath.getObjectName()));
}

Prevention

When it happens

Trigger: Calling FlinkCatalog.getFunction(functionPath) for any function, or Flink SQL resolution of a catalog function (not a built-in/temporary function) in a session bound to FlinkCatalog.

Common situations: Registering UDFs through the catalog instead of the job; SQL scripts referencing persistent catalog functions after switching the catalog to Iceberg; tooling that enumerates catalog functions.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12). Data as JSON: /api/errors/7acc896572d38422. Report an issue: GitHub.