quarkusio/quarkus · error · IllegalStateException

Unsupported value type: %s

Error message

Unsupported value type: %s

What it means

RootResource.posts throws "Failed to get user principal" when sec.getUserPrincipal() is null (NPE from getName()) or has a null name, after the body check passes. It means the REST endpoint was reached without an authenticated identity despite the test expecting Elytron to authenticate the caller.

Source

Thrown at core/builder/src/main/java/io/quarkus/builder/Json.java:411

                    if (!objectBuilder.isEmpty()) {
                        put(attribute, objectBuilder);
                    }
                }
            }
        }
    }

    static void appendValue(Appendable appendable, Object value, boolean skipEscapeCharacters) throws IOException {
        if (value instanceof JsonObjectBuilder) {
            appendable.append(((JsonObjectBuilder) value).build());
        } else if (value instanceof JsonArrayBuilder) {
            appendable.append(((JsonArrayBuilder) value).build());
        } else if (value instanceof String) {
            appendStringValue(appendable, value.toString(), skipEscapeCharacters);
        } else if (value instanceof Boolean || value instanceof Integer || value instanceof Long) {
            appendable.append(value.toString());
        } else {
            throw new IllegalStateException("Unsupported value type: " + value);
        }
    }

    static void appendStringValue(Appendable appendable, String value, boolean skipEscapeCharacters) throws IOException {
        appendable.append(CHAR_QUOTATION_MARK);
        if (skipEscapeCharacters) {
            appendable.append(value);
        } else {
            appendable.append(escape(value));
        }
        appendable.append(CHAR_QUOTATION_MARK);
    }

    /**
     * Escape quotation mark, reverse solidus and control characters (U+0000 through U+001F).
     *
     * @param value
     * @return escaped value

View on GitHub (pinned to e1c734241f)

Solutions

  1. Send valid basic-auth credentials with the POST.
  2. Configure quarkus.http.auth.permission policies to require authentication and a working elytron identity realm.
  3. Null-check sec.getUserPrincipal() before getName().
  4. Verify SecurityContext injection is backed by the Elytron identity (quarkus-elytron-security present).

Example fix

// before
if (sec.getUserPrincipal().getName() == null) {
    throw new RuntimeException("Failed to get user principal");
}
// after
if (sec.getUserPrincipal() == null) {
    throw new RuntimeException("Failed to get user principal");
}
Defensive patterns

Strategy: validation

Validate before calling

Objects.requireNonNull(fruit.getName(), "name is required for PUT /fruits/{id}");

Type guard

static boolean isUpdatable(Fruit f) {
    return f != null && f.getName() != null && !f.getName().isBlank();
}

Try / catch

try {
    given().body(fruit).put("/fruits/" + id);
} catch (WebApplicationException e) {
    if (e.getResponse().getStatus() == 422) { /* supply a name and retry */ }
    else throw e;
}

Prevention

When it happens

Trigger: POST with a valid text/plain body but no/invalid credentials, so SecurityContext.getUserPrincipal() returns null and .getName() throws.

Common situations: Missing Authorization header; quarkus.http.auth.policy/permission config not requiring auth for the path; elytron realm identity not found; principal propagated with null name.

Related errors


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