{"record":{"id":"08eac5519d522975","repo":"spring-projects/spring-ai","slug":"type-must-be-a-function-bifunction-function1-or","errorCode":null,"errorMessage":"Type must be a Function, BiFunction, Function1 or Function2. Found: ","messagePattern":"Type must be a Function, BiFunction, Function1 or Function2\\. Found: ","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"spring-ai-model/src/main/java/org/springframework/ai/tool/resolution/TypeResolverHelper.java","lineNumber":267,"sourceCode":"\t\t\tfunctionArgumentResolvableType = functionType.as(Supplier.class);\n\t\t}\n\t\telse if (Consumer.class.isAssignableFrom(resolvableClass)) {\n\t\t\tfunctionArgumentResolvableType = functionType.as(Consumer.class);\n\t\t}\n\t\telse if (KotlinDetector.isKotlinPresent()) {\n\t\t\tif (KotlinDelegate.isKotlinFunction(resolvableClass)) {\n\t\t\t\tfunctionArgumentResolvableType = KotlinDelegate.adaptToKotlinFunctionType(functionType);\n\t\t\t}\n\t\t\telse if (KotlinDelegate.isKotlinBiFunction(resolvableClass)) {\n\t\t\t\tfunctionArgumentResolvableType = KotlinDelegate.adaptToKotlinBiFunctionType(functionType);\n\t\t\t}\n\t\t\telse if (KotlinDelegate.isKotlinSupplier(resolvableClass)) {\n\t\t\t\tfunctionArgumentResolvableType = KotlinDelegate.adaptToKotlinSupplierType(functionType);\n\t\t\t}\n\t\t}\n\n\t\tif (functionArgumentResolvableType == ResolvableType.NONE) {\n\t\t\tthrow new IllegalArgumentException(\n\t\t\t\t\t\"Type must be a Function, BiFunction, Function1 or Function2. Found: \" + functionType);\n\t\t}\n\n\t\treturn functionArgumentResolvableType.getGeneric(argumentIndex);\n\t}\n\n\tprivate static final class KotlinDelegate {\n\n\t\tpublic static boolean isKotlinSupplier(Class<?> clazz) {\n\t\t\treturn Function0.class.isAssignableFrom(clazz);\n\t\t}\n\n\t\tpublic static ResolvableType adaptToKotlinSupplierType(ResolvableType resolvableType) {\n\t\t\treturn resolvableType.as(Function0.class);\n\t\t}\n\n\t\tpublic static boolean isKotlinFunction(Class<?> clazz) {\n\t\t\treturn Function1.class.isAssignableFrom(clazz);","sourceCodeStart":249,"sourceCodeEnd":285,"githubUrl":"https://github.com/spring-projects/spring-ai/blob/98a7beda4f29d80a71c5837eb4053b03a93a46f7/spring-ai-model/src/main/java/org/springframework/ai/tool/resolution/TypeResolverHelper.java#L249-L285","documentation":"Thrown when Spring AI tries to infer the input/output types of a functional bean but the bean's type is not a supported functional shape (Function, BiFunction, Kotlin Function1/Function2, or Supplier variants). The resolved generic type came back as ResolvableType.NONE.","triggerScenarios":"Registering a bean whose type implements none of Function/BiFunction/Consumer-type contracts (e.g. a custom interface, a 3-arg function, or a lambda typed only as Object) and then exposing it as a tool via FunctionToolCallback or ToolCallbacks.from.","commonSituations":"Using a custom functional interface instead of java.util.function.Function; Kotlin lambdas typed as Function3+; raw lambdas assigned to Object variables; generics erased so ResolvableType sees NONE.","solutions":["Change the bean to implement java.util.function.Function<I,O> (or BiFunction / Kotlin Function1/Function2)","Wrap unsupported types with an adapter lambda typed as Function","Give the lambda an explicit target type (Function<Input, Output> f = in -> ...) rather than var/Object","Specify the tool's input/output types explicitly instead of relying on type inference"],"exampleFix":"// before\n@Bean\npublic TriFunction<String, String, String, String> myTool() { ... }\n// after\n@Bean\npublic Function<MyRequest, String> myTool() {\n    return req -> doWork(req.a(), req.b());\n}","handlingStrategy":"type-guard","validationCode":"if (!(bean instanceof Function) && !(bean instanceof BiFunction) && !(bean instanceof Supplier)) {\n    throw new IllegalStateException(beanName + \" must be a Function/BiFunction/Supplier to be exposed as a tool\");\n}","typeGuard":"boolean isFunctionalTool(Object bean) {\n    return bean instanceof Function<?, ?> || bean instanceof BiFunction<?, ?, ?> || bean instanceof Supplier<?>;\n}","tryCatchPattern":null,"preventionTips":["Always type functional beans as java.util.function types, never Object or custom interfaces","Give lambdas explicit target types instead of var","Limit Kotlin lambdas to 1-2 parameters when exposing as tools"],"tags":["spring-ai","functional-beans","type-resolution"],"backgroundTag":"type-mismatch","analyzedSha":"98a7beda4f29d80a71c5837eb4053b03a93a46f7","analyzedAt":"2026-09-11T14:15:49.441Z","contentChangedAt":"2026-09-11T14:15:49.441Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}