private @NotNull <Result> CompletableFuture<Result> onValidThread(@NotNull TreePath path,
                                                                    @NotNull Function<? super Node, ? extends Result> function) {
    Object component = path.getLastPathComponent();
    if (component instanceof Node node) {
      return onValidThread(__ -> disposed || isNodeRemoved(node) ? null : function.apply(node));
    }

    CompletableFuture<Result> cancelledFuture = new CompletableFuture<>();
    cancelledFuture.completeExceptionally(createError("unexpected node: " + component));
    return cancelledFuture;
  }
private @NotNull <Result> CompletableFuture<Result> onValidThread(@NotNull TreePath path,
                                                                    @NotNull Function<? super Node, ? extends Result> function)