quarkusio/quarkus · error · IllegalArgumentException
Using `UNF` requires `SORTABLE`
Error message
Using `UNF` requires `SORTABLE`
What it means
In RediSearch, the UNF (un-normalized) field option is only meaningful for SORTABLE fields because it controls how the sort normalization is applied. FieldOptions.toArgs() throws IllegalArgumentException when unnormalized() (UNF) is set without sortable().
Solutions
- Add .sortable() before .unnormalized(), e.g. .asText().sortable().unnormalized()
- Remove the unnormalized() call if sortedness is not needed
Example fix
// before
args.field("name").asText().unnormalized(); // throws
// after
args.field("name").asText().sortable().unnormalized(); Defensive patterns
Strategy: validation
Validate before calling
if (wantUnf && !wantSortable) throw new IllegalStateException("UNF requires SORTABLE; add .sortable() or drop .unnormalized()");
FieldOptions opts = new FieldOptions().sortable();
if (wantUnf) opts.unnormalized(); Type guard
boolean validUnf(boolean unf, boolean sortable) {
return !unf || sortable;
} Try / catch
try {
args.field("name").asText(opts);
} catch (IllegalArgumentException e) {
if (e.getMessage().contains("UNF requires")) {
throw new IllegalStateException("Field option UNF used without SORTABLE", e);
}
throw e;
} Prevention
- Only use UNF on SORTABLE fields
- Read RediSearch option dependencies: UNF modifies sort normalization
- When removing sortable() in refactors, check for dependent options like unnormalized()
When it happens
Trigger: Calling FieldOptions methods like .unnormalized() without .sortable() on the same options object, e.g. args.field("name").asText().unnormalized(), then using it in a CreateArgs schema.
Common situations: Copying options from Redis docs/examples piecemeal and missing SORTABLE; misunderstanding UNF as a standalone feature; refactoring that removed sortable() but kept unnormalized().
Related errors
- Cannot use descending and ascending order at the same time
- Cannot use `ON HASH` and `ON JSON` at the same time
- The schema cannot be empty, you configure the indexed fields
- ANY can only be used if COUNT is also set
- ANY can only be used if COUNT is also set
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/6eca59a5750dc17e.
Report an issue: GitHub.
Appendix: source
Thrown at extensions/redis-client/runtime/src/main/java/io/quarkus/redis/datasource/search/FieldOptions.java:231
}
if (distanceMetric != null) {
list.add("DISTANCE_METRIC");
list.add(distanceMetric.name());
}
if (initialCap != null) {
list.add("INITIAL_CAP");
list.add(initialCap.toString());
}
if (blockSize != null) {
list.add("BLOCK_SIZE");
list.add(blockSize.toString());
}
if (sortable) {
list.add("SORTABLE");
}
if (unf) {
if (!sortable) {
throw new IllegalArgumentException("Using `UNF` requires `SORTABLE`");
}
list.add("UNF");
}
if (noStem) {
list.add("NOSTEM");
}
if (noIndex) {
list.add("NOINDEX");
}
if (phonetic != null) {
list.add("PHONETIC");
list.add(phonetic);
}
if (weight != -1) {
list.add("WEIGHT");
list.add(Double.toString(weight));
}
if (separator != 0) {View on GitHub (pinned to e1c734241f)