{"record":{"id":"f0bbb5d793e0a0b0","repo":"quarkusio/quarkus","slug":"unable-to-fully-read-json-value","errorCode":null,"errorMessage":"Unable to fully read json value","messagePattern":"Unable to fully read json value","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"core/builder/src/main/java/io/quarkus/builder/JsonReader.java","lineNumber":68,"sourceCode":"        JsonValue result = readValue();\n        ignoreWhitespace();\n        return result;\n    }\n\n    /**\n     * value\n     * |---- object\n     * |---- array\n     * |---- string\n     * |---- number\n     * |---- \"true\"\n     * |---- \"false\"\n     * |---- \"null\"\n     */\n    private JsonValue readValue() {\n        final int ch = peekChar();\n        if (ch < 0) {\n            throw new IllegalArgumentException(\"Unable to fully read json value\");\n        }\n\n        switch (ch) {\n            case '{':\n                return readObject();\n            case '[':\n                return readArray();\n            case '\"':\n                return readString();\n            case 't':\n                return readConstant(\"true\", JsonBoolean.TRUE);\n            case 'f':\n                return readConstant(\"false\", JsonBoolean.FALSE);\n            case 'n':\n                return readConstant(\"null\", JsonNull.INSTANCE);\n            default:\n                if (Character.isDigit(ch) || '-' == ch) {\n                    return readNumber(position);","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/core/builder/src/main/java/io/quarkus/builder/JsonReader.java#L50-L86","documentation":"RootResource.approval (GET) throws \"Failed to get user principal\" when the injected SecurityContext has no principal — getUserPrincipal() returns null and .getName() throws an NPE reported under this error. The endpoint demands an authenticated caller but the request arrived unauthenticated.","triggerScenarios":"GET to the resource without credentials, or with credentials the elytron realm rejects, so sec.getUserPrincipal() is null before getName().","commonSituations":"Anonymous GET allowed by config while test expects auth; wrong username/password; elytron security extension missing so SecurityContext is empty; expired session/token.","solutions":["Send valid authentication credentials with the GET.","Ensure quarkus.http.auth.permission policies require authentication for the path and the elytron realm resolves the user.","Null-check getUserPrincipal() before calling getName().","Confirm quarkus-elytron-security is on the classpath so the SecurityContext is populated."],"exampleFix":"// before\nif (sec.getUserPrincipal().getName() == null) {\n    throw new RuntimeException(\"Failed to get user principal\");\n}\n// after\nif (sec.getUserPrincipal() == null) {\n    throw new RuntimeException(\"Failed to get user principal\");\n}","handlingStrategy":"validation","validationCode":"if (given().header(\"tenantId\", tenant).get(\"/fruits/\" + id).getStatusCode() == 404) {\n    throw new IllegalStateException(\"Cannot update: fruit \" + id + \" missing in tenant \" + tenant);\n}","typeGuard":null,"tryCatchPattern":"Response r = given().header(\"tenantId\", tenant).body(fruit).put(\"/fruits/\" + id);\nif (r.getStatusCode() == 404) {\n    // recreate resource or fail fast with a clear message\n}","preventionTips":["Create-then-update in the same test/tenant to guarantee a valid id","Keep one tenant header value per test (constant/filter)","Re-fetch ids after any delete step","Check the active tenant mapping (schema) when 404s appear unexpectedly"],"tags":["rest","jaxrs","security","elytron"],"backgroundTag":"unauthenticated-request-no-principal","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}