private void checkAmbiguity(final @NonNull CommandNode<C> node) throws AmbiguousNodeException {
        if (node.isLeaf()) {
            return;
        }

        // List of child nodes that are not static arguments, but (parsed) variable ones
        final List<CommandNode<C>> childVariableArguments = node.children()
                .stream()
                .filter(n -> n.component() != null)
                .filter(n -> n.component().type() != CommandComponent.ComponentType.LITERAL)
                .collect(Collectors.toList());

        // If more than one child node exists with a variable argument, fail
        if (childVariableArguments.size() > 1) {
            final CommandNode<C> child = childVariableArguments.get(0);

            throw new AmbiguousNodeException(
                    node,
                    child,
                    node.children()
                            .stream()
                            .filter(n -> n.component() != null)
                            .collect(Collectors.toList())
            );
        }

        // List of child nodes that are static arguments, with fixed values
        final List<CommandNode<C>> childStaticArguments = node.children()
                .stream()
                .filter(n -> n.component() != null)
                .filter(n -> n.component().type() == CommandComponent.ComponentType.LITERAL)
                .collect(Collectors.toList());

        // Check none of the static arguments are equal to another one
        // This is done by filling a set and checking there are no duplicates
        final Set<String> checkedLiterals = new HashSet<>();
        for (final CommandNode<C> child : childStaticArguments) {
            for (final String nameOrAlias : child.component().aliases()) {
                if (!checkedLiterals.add(nameOrAlias)) {
                    // Same literal value, ambiguity detected
                    throw new AmbiguousNodeException(
                            node,
                            child,
                            node.children()
                                    .stream()
                                    .filter(n -> n.component() != null)
                                    .collect(Collectors.toList())
                    );
                }
            }
        }

        // Recursively check child nodes as well
        node.children().forEach(this::checkAmbiguity);
    }
Verifies that there is no illegal ambiguity in the given {@code node}.

@param node the node
@throws AmbiguousNodeException if the node breaks some ambiguity contract
cloud-core/src/main/java/org/incendo/cloud/CommandTree.java