{"record":{"id":"003a0f4fcda13e82","repo":"OpenFeign/feign","slug":"streamdecoder-supports-types-other-than-stream-wh","errorCode":null,"errorMessage":"StreamDecoder supports types other than stream. When type is not stream, the delegate decoder needs to be setting.","messagePattern":"StreamDecoder supports types other than stream\\. When type is not stream, the delegate decoder needs to be setting\\.","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/feign/stream/StreamDecoder.java","lineNumber":71,"sourceCode":" *   Stream<Contributor> contributors(@Param(\"owner\") String owner, @Param(\"repo\") String repo);\n * }</code>\n * </pre>\n */\npublic final class StreamDecoder implements Decoder {\n\n  private final Decoder iteratorDecoder;\n  private final Optional<Decoder> delegateDecoder;\n\n  StreamDecoder(Decoder iteratorDecoder, Decoder delegateDecoder) {\n    this.iteratorDecoder = iteratorDecoder;\n    this.delegateDecoder = Optional.ofNullable(delegateDecoder);\n  }\n\n  @Override\n  public Object decode(Response response, Type type) throws IOException, FeignException {\n    if (!isStream(type)) {\n      if (!delegateDecoder.isPresent()) {\n        throw new IllegalArgumentException(\n            \"StreamDecoder supports types other than stream. \"\n                + \"When type is not stream, the delegate decoder needs to be setting.\");\n      } else {\n        return delegateDecoder.get().decode(response, type);\n      }\n    }\n    ParameterizedType streamType = (ParameterizedType) type;\n    Iterator<?> iterator =\n        (Iterator<?>) iteratorDecoder.decode(response, new IteratorParameterizedType(streamType));\n\n    return StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, 0), false)\n        .onClose(\n            () -> {\n              if (iterator instanceof Closeable) {\n                ensureClosed((Closeable) iterator);\n              } else {\n                ensureClosed(response);\n              }","sourceCodeStart":53,"sourceCodeEnd":89,"githubUrl":"https://github.com/OpenFeign/feign/blob/e2a1e27560a1e68840c34f031afca88b36096e30/core/src/main/java/feign/stream/StreamDecoder.java#L53-L89","documentation":"StreamDecoder decodes streaming (Iterator/stream) response types itself, but for any other return type it must delegate to another Decoder. If no delegate decoder was configured and the method's return type is not a Stream type, it throws this IllegalArgumentException at decode time.","triggerScenarios":"Building a Feign client with StreamDecoder.create() (no delegate) or StreamDecoder.create(null) while an interface method returns a non-stream type (e.g., a plain POJO, List, String); the error fires when that method is invoked and the response is decoded.","commonSituations":"Mixing streaming endpoints and normal endpoints in one client but configuring only StreamDecoder without a wrapped fallback decoder; copy-pasting the streaming setup from docs onto a client with regular return types.","solutions":["Wrap a real decoder: use StreamDecoder.create(defaultDecoder) where defaultDecoder handles the non-stream types (e.g., new JacksonDecoder())","Change the method's return type to a Stream/Iterator type if streaming was intended","Catch IllegalArgumentException around the call as a last resort to detect misconfiguration early"],"exampleFix":"// before\nDecoder decoder = StreamDecoder.create(); // no delegate\n// after\nDecoder decoder = StreamDecoder.create(new JacksonDecoder(mapper)); // handles non-stream types","handlingStrategy":"validation","validationCode":"if (client has any non-Stream return types && decoder is StreamDecoder) {\n  throw new IllegalStateException(\"StreamDecoder requires a delegate decoder for non-stream types\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  return api.getItem(id);\n} catch (IllegalArgumentException e) {\n  if (e.getMessage().contains(\"delegate decoder\")) {\n    throw new IllegalStateException(\"configure StreamDecoder.create(delegate)\", e);\n  }\n  throw e;\n}","preventionTips":["Always pass a delegate: StreamDecoder.create(new JacksonDecoder())","Audit client interfaces for mixed Stream and non-Stream return types before configuring only a StreamDecoder","Add a startup test that invokes one method per return-type shape"],"tags":["java","feign","streaming","decoder","misconfiguration"],"backgroundTag":"missing-required-config","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"}