apache/iceberg · error

bind is not implemented

Error message

bind is not implemented

What it means

Transform.bind(Type) is a default method that throws UnsupportedOperationException('bind is not implemented') for Transform implementations that have not overridden it. The binding step resolves the transform into a SerializableFunction specialized for the given type; a custom Transform that skipped overriding bind cannot do this. It is raised at bind time (e.g. from boundReferences during partition evaluation), not at apply time.

Source

Thrown at api/src/main/java/org/apache/iceberg/transforms/Transform.java:60

   *
   * @param value a source value
   * @return a transformed partition value
   * @deprecated use {@link #bind(Type)} instead; will be removed in 2.0.0
   */
  @Deprecated
  default T apply(S value) {
    throw new UnsupportedOperationException(
        "apply(value) is deprecated, use bind(Type).apply(value)");
  }

  /**
   * Returns a function that applies this transform to values of the given {@link Type type}.
   *
   * @param type an Iceberg {@link Type}
   * @return a {@link Function} that applies this transform to values of the given type.
   */
  default SerializableFunction<S, T> bind(Type type) {
    throw new UnsupportedOperationException("bind is not implemented");
  }

  /**
   * Checks whether this function can be applied to the given {@link Type}.
   *
   * @param type a type
   * @return true if this transform can be applied to the type, false otherwise
   */
  boolean canTransform(Type type);

  /**
   * Returns the {@link Type} produced by this transform given a source type.
   *
   * @param sourceType a type
   * @return the result type created by the apply method for the given type
   */
  Type getResultType(Type sourceType);

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Override bind(Type) in the custom Transform to return a SerializableFunction for each supported type
  2. If the transform cannot support binding, throw a descriptive exception in canTransform(type) so it is rejected before bind is reached
  3. Migrate third-party/legacy Transform implementations to the bind()-based API

Example fix

// before
class MyTransform<S, T> implements Transform<S, T> {
  public T apply(S value) { return doIt(value); } // no bind override
}
// after
class MyTransform<S, T> implements Transform<S, T> {
  public SerializableFunction<S, T> bind(Type type) {
    return value -> doIt(value);
  }
}
Defensive patterns

Strategy: try-catch

Validate before calling

try { transform.bind(type); } catch (UnsupportedOperationException e) { /* custom transform does not support binding */ }

Type guard

if (transform.getClass().isAssignableFrom(CustomTransform.class)) {
  // verify it overrides bind before use in partition evaluation
}

Try / catch

try { fn = transform.bind(type); } catch (UnsupportedOperationException e) { throw new IllegalArgumentException("Transform " + transform + " does not support binding for type " + type, e); }

Prevention

When it happens

Trigger: Calling bind(type) on a custom Transform subclass that overrides apply/canTransform/toHumanString but not bind; using a hand-rolled Transform implementation in partition expression evaluation paths that call boundReferences.

Common situations: Implementing a custom partition transform for a spec read from an external system and forgetting bind; third-party Transform implementations that predate the bind() API and were never migrated.

Related errors


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