{"record":{"id":"6d10e01c05f2028c","repo":"OpenFeign/feign","slug":"at-least-one-decoder-is-required","errorCode":null,"errorMessage":"at least one decoder is required","messagePattern":"at least one decoder is required","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/feign/codec/MultiDecoder.java","lineNumber":241,"sourceCode":"     *     .add(DecoderPredicate.any(), new DefaultDecoder())\n     *     .build();\n     * </pre>\n     *\n     * @param predicate narrows what the decoder handles\n     * @param decoder the decoder to delegate to\n     */\n    public Builder narrow(DecoderPredicate predicate, Decoder decoder) {\n      return add(PredicatedDecoder.narrowing(predicate, decoder));\n    }\n\n    /**\n     * Builds the multi-decoder.\n     *\n     * @throws IllegalStateException if no decoder was added\n     */\n    public MultiDecoder build() {\n      if (decoders.isEmpty()) {\n        throw new IllegalStateException(\"at least one decoder is required\");\n      }\n      return new MultiDecoder(decoders);\n    }\n  }\n}\n","sourceCodeStart":223,"sourceCodeEnd":247,"githubUrl":"https://github.com/OpenFeign/feign/blob/e2a1e27560a1e68840c34f031afca88b36096e30/core/src/main/java/feign/codec/MultiDecoder.java#L223-L247","documentation":"The MultiDecoder.Builder requires at least one decoder before building; calling build() on an empty builder throws this IllegalStateException immediately. It is a fail-fast guard so a misconfigured client never reaches runtime with no way to decode responses.","triggerScenarios":"Calling new MultiDecoder.Builder().build() (or a wrapper that builds it) without ever calling add(...) / withDefaultDecoder(...).","commonSituations":"Programmatic Feign.builder() configuration assembled from empty conditional lists (e.g. codecs added only when certain flags/classes are present, so the list ends up empty); copy-pasted builder code where the add lines were deleted; framework glue code constructing the builder dynamically.","solutions":["Add at least one decoder before build(), e.g. .add(new JacksonDecoder())","If decoders come from a dynamic list, guard the build: only build the MultiDecoder when the list is non-empty, otherwise use a default decoder","Check whether an optional codec dependency is missing so the conditional add was skipped"],"exampleFix":"// before\nMultiDecoder d = new MultiDecoder.Builder().build();\n// after\nMultiDecoder d = new MultiDecoder.Builder().add(new Decoder.Default()).build();","handlingStrategy":"validation","validationCode":"if (decoders.isEmpty()) {\n  decoders.add(new Decoder.Default()); // or fail fast with a clear config error\n}\nMultiDecoder decoder = new MultiDecoder.Builder().add(decoders.toArray(new Decoder[0])).build();","typeGuard":null,"tryCatchPattern":"try {\n  this.decoder = multiDecoderBuilder.build();\n} catch (IllegalStateException e) {\n  if (e.getMessage().contains(\"at least one decoder\")) {\n    throw new ConfigurationException(\"No decoders registered for Feign client\", e);\n  }\n  throw e;\n}","preventionTips":["Never call build() on a builder assembled from a possibly-empty dynamic list; append a default first","Unit-test client factory methods with assertions that decoders are non-empty","Centralize Feign client construction so decoder registration is in one audited place"],"tags":["feign","configuration","builder","empty-collection"],"backgroundTag":"missing-required-argument","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"}