quarkusio/quarkus · error · IllegalArgumentException

Unknown class: ${token}

Error message

Unknown class: ${token}

What it means

TypeParser parses configuration type strings (e.g. in Dev UI / config class name references) into java.lang.reflect Types. parseClassType loads the token with Class.forName; if the class is not found on the thread context classloader, this IllegalArgumentException wrapping the ClassNotFoundException is thrown.

Source

Thrown at core/deployment/src/main/java/io/quarkus/deployment/types/TypeParser.java:165

            case "short" -> short.class;
            case "int" -> int.class;
            case "long" -> long.class;
            case "float" -> float.class;
            case "double" -> double.class;
            case "char" -> char.class;
            default -> throw unexpected(token);
        };
    }

    private boolean isClassType(String token) {
        return !token.isEmpty() && Character.isJavaIdentifierStart(token.charAt(0));
    }

    private Type parseClassType(String token) {
        try {
            return Class.forName(token, true, Thread.currentThread().getContextClassLoader());
        } catch (ClassNotFoundException e) {
            throw new IllegalArgumentException("Unknown class: " + token, e);
        }
    }

    // ---

    private void expect(String expected) {
        String token = nextToken();
        if (!expected.equals(token)) {
            throw unexpected(token);
        }
    }

    private IllegalArgumentException unexpected(String token) {
        if (token.isEmpty()) {
            throw new IllegalArgumentException("Unexpected end of input: " + str);
        }
        return new IllegalArgumentException("Unexpected token '" + token + "' at position " + (pos - token.length())
                + ": " + str);

View on GitHub (pinned to e1c734241f)

Solutions

  1. Correct the fully qualified class name in the type string
  2. Add the dependency/jar containing the class to the runtime classpath
  3. Verify the class is not only available at deployment time — runtime modules need it at runtime too
  4. Check for package renames in recent library upgrades and update the type string

Example fix

// before
parse("java.util.List<com.acme.old.Dto>")
// after
parse("java.util.List<com.acme.api.Dto>")
Defensive patterns

Strategy: validation

Validate before calling

void checkTypeToken(String token) throws ClassNotFoundException {
    String cls = token.replaceAll("<.*>", "").trim();
    Class.forName(cls, false, Thread.currentThread().getContextClassLoader());
}

Try / catch

try {
    type = TypeParser.parse(typeString);
} catch (IllegalArgumentException e) {
    if (e.getCause() instanceof ClassNotFoundException cnfe) {
        // log cnfe.getMessage() and fix the class name/classpath
    }
    throw e;
}

Prevention

When it happens

Trigger: In parseClassType (called from result and parseArrayType): a token representing a class or generic type argument (e.g. inside List<SomeType>) cannot be loaded via TCCL Class.forName.

Common situations: Typo in a fully qualified class name inside a generic type string; class removed/renamed after refactor while an old type string persisted (e.g. in stored config or Dev UI requests); class in a module not visible to the runtime classloader; missing dependency containing the type.

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/6722842616aafbf3. Report an issue: GitHub.