apache/flink · error · InvalidTypesException

The return type of function '{functionName}' could not be de

Error message

The return type of function '{functionName}' could not be determined automatically, due to type erasure. You can give type information hints by using the returns(...) method on the result of the transformation call, or by letting your function implement the 'ResultTypeQueryable' interface.

What it means

When Flink cannot infer a transformation's return type (typically due to generic type erasure), it stores a MissingTypeInfo placeholder. On the first getOutputType() call it throws InvalidTypesException telling the user the type could not be determined and to supply a hint, surfacing the problem at job-construction time rather than at runtime.

Source

Thrown at flink-core/src/main/java/org/apache/flink/api/dag/Transformation.java:581

            throw new IllegalStateException(
                    "TypeInformation cannot be filled in for the type after it has been used. "
                            + "Please make sure that the type info hints are the first call after"
                            + " the transformation function, "
                            + "before any access to types or semantic properties, etc.");
        }
        this.outputType = outputType;
    }

    /**
     * Returns the output type of this {@code Transformation} as a {@link TypeInformation}. Once
     * this is used once the output type cannot be changed anymore using {@link #setOutputType}.
     *
     * @return The output type of this {@code Transformation}
     */
    public TypeInformation<T> getOutputType() {
        if (outputType instanceof MissingTypeInfo) {
            MissingTypeInfo typeInfo = (MissingTypeInfo) this.outputType;
            throw new InvalidTypesException(
                    "The return type of function '"
                            + typeInfo.getFunctionName()
                            + "' could not be determined automatically, due to type erasure. "
                            + "You can give type information hints by using the returns(...) "
                            + "method on the result of the transformation call, or by letting "
                            + "your function implement the 'ResultTypeQueryable' "
                            + "interface.",
                    typeInfo.getTypeException());
        }
        typeUsed = true;
        return this.outputType;
    }

    /**
     * Set the buffer timeout of this {@code Transformation}. The timeout defines how long data may
     * linger in a partially full buffer before being sent over the network.
     *
     * <p>Lower timeouts lead to lower tail latencies, but may affect throughput. For Flink 1.5+,

View on GitHub (pinned to 2f3c205e92)

Solutions

  1. Add .returns(TypeInformation.of(...)) as the first call after the transformation function.
  2. Implement ResultTypeQueryable on your function and return the TypeInformation explicitly.
  3. Replace the lambda with a named class so Flink can introspect the generic method signature.
  4. Use Types.POJO(...) / Types.TUPLE(...) hints to make the return type concrete.

Example fix

// before: data.map(x -> new MyResult(...))  // type erased -> MissingTypeInfo -> throws on getOutputType
// after:  data.map(x -> new MyResult(...)).returns(TypeInformation.of(MyResult.class))
Defensive patterns

Strategy: try-catch

Try / catch

try {
    TypeInformation<T> out = transform.getOutputType();
} catch (InvalidTypesException e) {
    if (e.getMessage().contains("could not be determined automatically")) {
        // Add .returns(...) after the transformation or implement ResultTypeQueryable
        log.error("Return type erased; supply a type hint or implement ResultTypeQueryable");
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling getOutputType() (or any operation needing the output type) on a transformation whose function returns a generic type Flink could not resolve — e.g., a lambda or anonymous MapFunction returning List<X> or a parameterized POJO whose type argument is erased.

Common situations: Lambdas or anonymous functions returning generic collections/POJOs where the type parameter is erased; Tuple returns without explicit TupleTypeInfo; nested generics; using .map(x -> new Result(...)) for a non-final Result class whose generic signature is invisible.

Related errors


AI-assisted analysis of apache/flink@2f3c205e92 (2026-08-14). Data as JSON: /api/errors/5b6b028937c4d81b. Report an issue: GitHub.