apache/iceberg · error · NoSuchProcedureException

Procedure ${ident} not found

Error message

Procedure ${ident} not found

What it means

BaseCatalog.loadProcedure resolves a procedure by name through SparkProcedures.newBuilder; when the name is not a registered Iceberg procedure it throws NoSuchProcedureException ('Procedure <ident> not found'). Iceberg only registers a fixed set of procedures (e.g. rewrite_data_files, expire_snapshots), so anything else fails lookup.

Source

Thrown at spark/v3.5/spark/src/main/java/org/apache/iceberg/spark/BaseCatalog.java:61

  private static final boolean USE_NULLABLE_QUERY_SCHEMA_CTAS_RTAS_DEFAULT = true;

  private boolean useNullableQuerySchema = USE_NULLABLE_QUERY_SCHEMA_CTAS_RTAS_DEFAULT;

  @Override
  public Procedure loadProcedure(Identifier ident) throws NoSuchProcedureException {
    String[] namespace = ident.namespace();
    String name = ident.name();

    // namespace resolution is case insensitive until we have a way to configure case sensitivity in
    // catalogs
    if (isSystemNamespace(namespace)) {
      ProcedureBuilder builder = SparkProcedures.newBuilder(name);
      if (builder != null) {
        return builder.withTableCatalog(this).build();
      }
    }

    throw new NoSuchProcedureException(ident);
  }

  @Override
  public boolean isFunctionNamespace(String[] namespace) {
    // Allow for empty namespace, as Spark's storage partitioned joins look up
    // the corresponding functions to generate transforms for partitioning
    // with an empty namespace, such as `bucket`.
    // Otherwise, use `system` namespace.
    return namespace.length == 0 || isSystemNamespace(namespace);
  }

  @Override
  public boolean isExistingNamespace(String[] namespace) {
    return namespaceExists(namespace);
  }

  @Override
  public void initialize(String name, CaseInsensitiveStringMap options) {

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Check spelling and the exact procedure list for your Iceberg/Spark version (org.apache.iceberg.spark.procedures.SparkProcedures).
  2. Upgrade the iceberg-spark runtime to a version that registers the procedure you need.
  3. Route non-Iceberg procedures to Spark's own function/procedure mechanisms instead of catalog.system.
  4. Qualify the CALL correctly: procedures must be invoked on the Iceberg catalog's system namespace, e.g. CALL my_catalog.system.rewrite_data_files(...).

Example fix

// before
CALL iceberg.system.compact_table(table => 'db.t');
// after
CALL iceberg.system.rewrite_data_files(table => 'db.t');
Defensive patterns

Strategy: validation

Validate before calling

// Java-side check before emitting CALL SQL
if (!SparkProcedures.names().contains(procedureName)) {
  throw new IllegalArgumentException("Unknown Iceberg procedure: " + procedureName);
}

Try / catch

try { spark.sql("CALL " + ident); } catch (NoSuchProcedureException e) { /* list available procedures and fail fast with guidance */ }

Prevention

When it happens

Trigger: CALL catalog.system.some_procedure(...) in Spark where some_procedure is not an Iceberg procedure; typo in procedure name; calling a Spark-4.x-only or newer-version procedure on Spark 3.5; invoking a non-Iceberg procedure through the Iceberg catalog instead of the built-in Spark function registry.

Common situations: Copy-pasted SQL from docs/blogs referencing a procedure that doesn't exist in the installed Iceberg version; version drift between docs (newer Iceberg) and runtime (older); confusing catalog system procedures with Spark built-in functions.

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


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