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
- Override bind(Type) in the custom Transform to return a SerializableFunction for each supported type
- If the transform cannot support binding, throw a descriptive exception in canTransform(type) so it is rejected before bind is reached
- 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
- Always override bind(Type) when implementing custom Transforms
- Test custom transforms through the bind() path, not just apply()
- Use canTransform(type) to reject types the transform cannot bind to
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
- Unsupported time unit: + granularity
- Unsupported time unit: + timestampUnit
- apply(value) is deprecated, use bind(Type).apply(value)
- Unsupported binary type: + value.getClass()
- Cannot truncate type: + type
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/e7d3611d9c7bbd77.
Report an issue: GitHub.