{"record":{"id":"5f498ecd09a9c8a9","repo":"OpenFeign/feign","slug":"end-of-methodinterceptor-chain","errorCode":null,"errorMessage":"end of MethodInterceptor chain","messagePattern":"end of MethodInterceptor chain","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/feign/interceptor/MethodInterceptor.java","lineNumber":86,"sourceCode":"    return invocation -> intercept(invocation, chain);\n  }\n\n  /**\n   * Returns a new {@link MethodInterceptor} that invokes the current interceptor first and then the\n   * one passed in.\n   */\n  default MethodInterceptor andThen(MethodInterceptor next) {\n    return (invocation, chain) ->\n        intercept(invocation, nextInvocation -> next.intercept(nextInvocation, chain));\n  }\n\n  /** Contract for delegation to the rest of the chain. */\n  interface Chain {\n\n    /** Sentinel end-of-chain that throws if invoked; the framework provides a real terminal. */\n    Chain DEFAULT =\n        invocation -> {\n          throw new UnsupportedOperationException(\"end of MethodInterceptor chain\");\n        };\n\n    /**\n     * Delegate to the rest of the chain.\n     *\n     * @param invocation invocation context (typically the same instance received by {@link\n     *     #intercept(Invocation, Chain)})\n     * @return value produced by the downstream chain\n     */\n    Object next(Invocation invocation) throws Throwable;\n  }\n}\n","sourceCodeStart":68,"sourceCodeEnd":99,"githubUrl":"https://github.com/OpenFeign/feign/blob/e2a1e27560a1e68840c34f031afca88b36096e30/core/src/main/java/feign/interceptor/MethodInterceptor.java#L68-L99","documentation":"This UnsupportedOperationException is thrown by MethodInterceptor.Chain.DEFAULT, a sentinel lambda that exists only to mark 'no more interceptors'. The Feign framework normally supplies a real terminal chain element that invokes the target method; if this sentinel is ever invoked, it means the interceptor chain was built without a terminal element, so there is nothing to delegate to.","triggerScenarios":"A MethodInterceptor implementation calls chain.doInvoke(...) (or invokes the Chain it received) when the chain it was handed is the DEFAULT sentinel — i.e., the chain was assembled or passed incorrectly, or a custom/provided chain has no real terminal invocation appended after the last interceptor.","commonSituations":"Writing a custom interceptor pipeline that appends interceptors but forgets to terminate with the actual method invocation; reusing a Chain object outside normal Feign.Builder invocation flow; tests or code that directly invoke Chain.DEFAULT.","solutions":["Do not invoke the DEFAULT sentinel; ensure your interceptor only delegates when it received a real chain from Feign's invocation pipeline","If building an interceptor chain yourself, always terminate it with the element that actually invokes the MethodHandler/target method","Check that you are using Feign.Builder()...build() so the framework installs the real terminal chain, not a hand-rolled one"],"exampleFix":"// before\npublic Object intercept(MethodInvocation invocation, Chain chain) {\n  return chain.doInvoke(invocation); // chain may be the DEFAULT sentinel in a hand-built chain\n}\n// after\npublic Object intercept(MethodInvocation invocation, Chain chain) {\n  if (chain == MethodInterceptor.Chain.DEFAULT) {\n    throw new IllegalStateException(\"interceptor chain was never terminated with the real invoker\");\n  }\n  return chain.doInvoke(invocation);\n}","handlingStrategy":"type-guard","validationCode":"if (chain == MethodInterceptor.Chain.DEFAULT) {\n  throw new IllegalStateException(\"interceptor chain not terminated; use the chain provided by Feign's invocation pipeline\");\n}","typeGuard":"boolean chainIsTerminable(MethodInterceptor.Chain chain) {\n  return chain != MethodInterceptor.Chain.DEFAULT;\n}","tryCatchPattern":null,"preventionTips":["Never invoke Chain.DEFAULT directly; treat it as a marker only","Always build clients through Feign.Builder so the framework installs the terminal invoker","Unit-test custom interceptor chains end-to-end (proxy invocation, not just interceptor logic)"],"tags":["java","feign","aop","interceptor-chain"],"backgroundTag":"unsupported-operation","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"}