OpenFeign/feign · error · UnsupportedOperationException

end of MethodInterceptor chain

Error message

end of MethodInterceptor chain

What it means

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.

Solutions

  1. Do not invoke the DEFAULT sentinel; ensure your interceptor only delegates when it received a real chain from Feign's invocation pipeline
  2. If building an interceptor chain yourself, always terminate it with the element that actually invokes the MethodHandler/target method
  3. Check that you are using Feign.Builder()...build() so the framework installs the real terminal chain, not a hand-rolled one

Example fix

// before
public Object intercept(MethodInvocation invocation, Chain chain) {
  return chain.doInvoke(invocation); // chain may be the DEFAULT sentinel in a hand-built chain
}
// after
public Object intercept(MethodInvocation invocation, Chain chain) {
  if (chain == MethodInterceptor.Chain.DEFAULT) {
    throw new IllegalStateException("interceptor chain was never terminated with the real invoker");
  }
  return chain.doInvoke(invocation);
}
Defensive patterns

Strategy: type-guard

Validate before calling

if (chain == MethodInterceptor.Chain.DEFAULT) {
  throw new IllegalStateException("interceptor chain not terminated; use the chain provided by Feign's invocation pipeline");
}

Type guard

boolean chainIsTerminable(MethodInterceptor.Chain chain) {
  return chain != MethodInterceptor.Chain.DEFAULT;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of OpenFeign/feign@e2a1e27560 (2026-09-10). Data as JSON: /api/errors/5f498ecd09a9c8a9. Report an issue: GitHub.

Appendix: source

Thrown at core/src/main/java/feign/interceptor/MethodInterceptor.java:86

    return invocation -> intercept(invocation, chain);
  }

  /**
   * Returns a new {@link MethodInterceptor} that invokes the current interceptor first and then the
   * one passed in.
   */
  default MethodInterceptor andThen(MethodInterceptor next) {
    return (invocation, chain) ->
        intercept(invocation, nextInvocation -> next.intercept(nextInvocation, chain));
  }

  /** Contract for delegation to the rest of the chain. */
  interface Chain {

    /** Sentinel end-of-chain that throws if invoked; the framework provides a real terminal. */
    Chain DEFAULT =
        invocation -> {
          throw new UnsupportedOperationException("end of MethodInterceptor chain");
        };

    /**
     * Delegate to the rest of the chain.
     *
     * @param invocation invocation context (typically the same instance received by {@link
     *     #intercept(Invocation, Chain)})
     * @return value produced by the downstream chain
     */
    Object next(Invocation invocation) throws Throwable;
  }
}

View on GitHub (pinned to e2a1e27560)