halo-dev/halo · warning · IllegalArgumentException

Unsupported sort value: {}

Error message

Unsupported sort value: {}

What it means

PostSorter.from(PostSorter) builds a Comparator for posts. It returns the default comparator for null, handles CREATE_TIME and PUBLISH_TIME, and otherwise throws IllegalArgumentException. Because the enum only declares those two constants and null is handled, the throw is effectively a defensive default-arm guard — unreachable through the public API unless the enum is extended without updating from().

Source

Thrown at application/src/main/java/run/halo/app/content/PostSorter.java:56

     *
     * @param sorter a {@link PostSorter}
     * @return a {@link Comparator} of {@link Post}
     */
    public static Comparator<Post> from(PostSorter sorter) {
        if (sorter == null) {
            return defaultComparator();
        }
        if (CREATE_TIME.equals(sorter)) {
            Function<Post, Instant> comparatorFunc = post -> post.getMetadata().getCreationTimestamp();
            return Comparator.comparing(comparatorFunc).thenComparing(name);
        }

        if (PUBLISH_TIME.equals(sorter)) {
            Function<Post, Instant> comparatorFunc = post -> post.getSpec().getPublishTime();
            return Comparator.comparing(comparatorFunc, Comparators.nullsLow()).thenComparing(name);
        }

        throw new IllegalArgumentException("Unsupported sort value: " + sorter);
    }

    static PostSorter convertFrom(String sort) {
        for (PostSorter sorter : values()) {
            if (sorter.name().equalsIgnoreCase(sort)) {
                return sorter;
            }
        }
        return null;
    }

    static Comparator<Post> defaultComparator() {
        Function<Post, Instant> createTime = post -> post.getMetadata().getCreationTimestamp();
        return Comparator.comparing(createTime).thenComparing(name);
    }
}

View on GitHub (pinned to d2f5165f9c)

Solutions

  1. If you added a new PostSorter constant, add the matching branch in from() before using it.
  2. Prefer routing string input through convertFrom(String), which returns null (and thus the default comparator) for unknown values.
  3. If calling from() with an externally supplied sorter, normalize unknown values to null first.

Example fix

// before
public enum PostSorter { PUBLISH_TIME, CREATE_TIME, UPDATE_TIME }
// ... from() has no UPDATE_TIME branch -> throws

// after
if (UPDATE_TIME.equals(sorter)) {
    Function<Post, Instant> comparatorFunc =
        post -> post.getMetadata()getUpdateTimestamp();
    return Comparator.comparing(comparatorFunc).thenComparing(name);
}
Defensive patterns

Strategy: validation

Validate before calling

// Use the string-based entrypoint, which returns null for unknown sorts:
PostSorter sorter = PostSorter.convertFrom(sortStr); // null -> default comparator
Comparator<Post> c = PostSorter.from(sorter);

Type guard

static boolean isKnownSorter(PostSorter s) {
    return s == null || s == PostSorter.CREATE_TIME || s == PostSorter.PUBLISH_TIME;
}

Prevention

When it happens

Trigger: Calling PostSorter.from(someSorter) where someSorter is a non-null value that is neither CREATE_TIME nor PUBLISH_TIME. In practice this requires adding a new enum constant and forgetting to branch on it, or injecting a value via reflection/unsafe.

Common situations: A future developer adds a third sort constant (e.g. UPDATE_TIME) to PostSorter without adding a branch in from(); then any call with the new constant throws at runtime. The public entrypoint convertFrom(String) maps unknown strings to null, so normal callers never reach this throw.

Related errors


AI-assisted analysis of halo-dev/halo@d2f5165f9c (2026-08-14). Data as JSON: /api/errors/ba953c8107e5dc59. Report an issue: GitHub.