{"record":{"id":"0469751f76e4fa89","repo":"OpenFeign/feign","slug":"method-s-can-t-have-continuation-argument-only-k","errorCode":null,"errorMessage":"Method %s can't have continuation argument, only kotlin method is allowed","messagePattern":"Method (.+?) can't have continuation argument, only kotlin method is allowed","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"kotlin/src/main/java/feign/kotlin/KotlinMethodInfo.java","lineNumber":42,"sourceCode":"import java.util.concurrent.CompletableFuture;\n\nclass KotlinMethodInfo extends MethodInfo {\n\n  KotlinMethodInfo(Type underlyingReturnType, boolean asyncReturnType) {\n    super(underlyingReturnType, asyncReturnType);\n  }\n\n  static KotlinMethodInfo createInstance(Class<?> targetType, Method method) {\n    final Type type = Types.resolve(targetType, targetType, method.getGenericReturnType());\n\n    Type underlyingReturnType;\n    boolean asyncReturnType;\n    if (MethodKt.isSuspend(method)) {\n      asyncReturnType = true;\n      underlyingReturnType = MethodKt.getKotlinMethodReturnType(method);\n      if (underlyingReturnType == null) {\n        String configKey = Feign.configKey(targetType, method);\n        throw new IllegalArgumentException(\n            String.format(\n                \"Method %s can't have continuation argument, only kotlin method is allowed\",\n                configKey));\n      }\n    } else if (type instanceof ParameterizedType\n        && Types.getRawType(type).isAssignableFrom(CompletableFuture.class)) {\n      asyncReturnType = true;\n      underlyingReturnType = ((ParameterizedType) type).getActualTypeArguments()[0];\n    } else {\n      asyncReturnType = false;\n      underlyingReturnType = type;\n    }\n\n    return new KotlinMethodInfo(underlyingReturnType, asyncReturnType);\n  }\n}\n","sourceCodeStart":24,"sourceCodeEnd":59,"githubUrl":"https://github.com/OpenFeign/feign/blob/e2a1e27560a1e68840c34f031afca88b36096e30/kotlin/src/main/java/feign/kotlin/KotlinMethodInfo.java#L24-L59","documentation":"KotlinMethodInfo.createInstance() validates that a method detected as a Kotlin suspend function actually has a resolvable Kotlin return type. If MethodKt.isSuspend(method) is true but getKotlinMethodReturnType returns null, it throws IllegalArgumentException stating the method can't have a continuation argument unless it is a proper Kotlin method.","triggerScenarios":"Registering a Feign target interface whose method is a suspend function compiled without Kotlin metadata, or a method whose last parameter is a Continuation but which is not a genuine suspend function (e.g. hand-written or processed by bytecode tools that strip metadata).","commonSituations":"Mixing Kotlin and Java modules where the interface was recompiled/obfuscated; using the feign-kotlin module with an interface written in Java that takes a kotlin.coroutines.Continuation parameter; Kotlin version mismatches altering metadata the reflection helpers rely on.","solutions":["Ensure the interface is authored in Kotlin and compiled with the same/m compatible Kotlin version as feign-kotlin","Remove the Continuation parameter from Java-declared methods; declare them as suspend fun in Kotlin instead","Verify the jar containing the interface was not obfuscated/processed in a way that strips @Metadata annotations","Check the generated configKey in the message to identify the offending method and fix its declaration"],"exampleFix":"// before (Java interface)\nResponse getData(Continuation<? super Response> cont);\n// after (Kotlin interface)\ninterface Api { suspend fun getData(): Response }","handlingStrategy":"validation","validationCode":"// before building the target\nMethod m = Api.class.getMethod(\"getData\");\nif (MethodKt.isSuspend(m) && MethodKt.getKotlinMethodReturnType(m) == null) {\n  throw new IllegalStateException(\"Method \" + m + \" must be declared as suspend fun in Kotlin\");\n}","typeGuard":null,"tryCatchPattern":"try { Feign.builder().target(Api.class, url); }\ncatch (IllegalArgumentException e) {\n  if (e.getMessage().contains(\"continuation argument\")) throw new IllegalStateException(\"Declare the method as suspend fun in Kotlin\", e);\n  throw e;\n}","preventionTips":["Define Feign interfaces in Kotlin when using feign-kotlin suspend support","Keep Kotlin stdlib/plugin versions consistent across modules","Avoid bytecode post-processing/obfuscation of Feign interface jars"],"tags":["kotlin","coroutines","suspend","feign","illegal-argument"],"backgroundTag":"invalid-argument-value","analyzedSha":"e2a1e27560a1e68840c34f031afca88b36096e30","analyzedAt":"2026-09-10T12:37:37.238Z","contentChangedAt":"2026-09-10T12:37:37.238Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}