alibaba/nacos · warning · UnsupportedOperationException

not support to cancel fuzzy watch

Error message

not support to cancel fuzzy watch

What it means

Thrown by the anonymous Future.cancel(boolean) returned from NamingFuzzyWatchContext.createNewFuture(). Fuzzy watch is a server-driven push model; the client cannot cancel the underlying server subscription through the Future, so cancel() is intentionally unsupported. isCancelled() always returns false. This is a deliberate API contract, not a bug.

Source

Thrown at client/src/main/java/com/alibaba/nacos/client/naming/cache/NamingFuzzyWatchContext.java:425

            return getFuzzyWatchEventWatcherWrappers();
        } else {
            return getFuzzyWatchEventWatcherWrappers().stream()
                .filter(a -> a.getUuid().equals(uuid))
                .collect(Collectors.toSet());
        }
    }
    
    /**
     * create a new future of this context.
     *
     * @return
     */
    public Future<ListView<String>> createNewFuture() {
        Future<ListView<String>> completableFuture = new Future<ListView<String>>() {
            
            @Override
            public boolean cancel(boolean mayInterruptIfRunning) {
                throw new UnsupportedOperationException("not support to cancel fuzzy watch");
            }
            
            @Override
            public boolean isCancelled() {
                return false;
            }
            
            @Override
            public boolean isDone() {
                return NamingFuzzyWatchContext.this.initializationCompleted.get();
            }
            
            @Override
            public ListView<String> get() throws InterruptedException {
                synchronized (NamingFuzzyWatchContext.this) {
                    while (!NamingFuzzyWatchContext.this.initializationCompleted.get()) {
                        NamingFuzzyWatchContext.this.wait();
                    }

View on GitHub (pinned to 9b989acdf1)

Solutions

  1. Do not call cancel() on fuzzy-watch futures; manage the subscription lifecycle via the NamingFuzzyWatchServiceListHolder (register/unregister watcher) instead.
  2. If you need cancellation semantics, wrap the future.get(timeout) call and discard the result on timeout rather than calling cancel().
  3. Guard third-party code that may invoke cancel() by checking the future source before calling it.

Example fix

// before
Future<ListView<String>> f = context.createNewFuture();
f.cancel(true); // throws UnsupportedOperationException

// after — use timeout on get() instead of cancel()
ListView<String> result = f.get(5, TimeUnit.SECONDS);
Defensive patterns

Strategy: type-guard

Validate before calling

// Never call cancel() on fuzzy-watch futures; use get(timeout) instead
ListView<String> keys = future.get(5, TimeUnit.SECONDS);

Type guard

public static boolean isCancellable(Future<?> f) { // fuzzy-watch futures throw on cancel; treat them as non-cancellable return false; }

Prevention

When it happens

Trigger: Calling future.cancel(true/false) on the Future obtained from a fuzzy watch context; passing the fuzzy-watch Future to a framework that cancels futures (e.g. timeout/cancellation utilities, CompletableFuture orchestration).

Common situations: Generic async utilities that call cancel() on any Future they manage; copying patterns from normal CompletableFuture usage into fuzzy-watch code; cleanup hooks that cancel futures.

Related errors


AI-assisted analysis of alibaba/nacos@9b989acdf1 (2026-08-14). Data as JSON: /api/errors/df2af14c6d0b0017. Report an issue: GitHub.