{"record":{"id":"764aef02c5585933","repo":"quarkusio/quarkus","slug":"cannot-consume-produce-interface-or-abstract-class","errorCode":null,"errorMessage":"Cannot consume/produce interface or abstract class build items","messagePattern":"Cannot consume/produce interface or abstract class build items","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"core/builder/src/main/java/io/quarkus/builder/BuildStepBuilder.java","lineNumber":260,"sourceCode":"    Set<ItemId> getRealProduces() {\n        final LinkedHashMap<ItemId, Produce> map = new LinkedHashMap<>(produces);\n        map.entrySet().removeIf(e -> e.getValue().getConstraint() == Constraint.ORDER_ONLY);\n        return map.keySet();\n    }\n\n    @Override\n    public String toString() {\n        StringBuilder builder = new StringBuilder();\n        builder.append(\"BuildStep [\");\n        builder.append(buildStep);\n        builder.append(\"]\");\n        return builder.toString();\n    }\n\n    private void checkType(Class<?> type) {\n        int modifiers = type.getModifiers();\n        if (Modifier.isInterface(modifiers) || Modifier.isAbstract(modifiers)) {\n            throw new IllegalArgumentException(\"Cannot consume/produce interface or abstract class build items\");\n        }\n    }\n}\n","sourceCodeStart":242,"sourceCodeEnd":264,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/core/builder/src/main/java/io/quarkus/builder/BuildStepBuilder.java#L242-L264","documentation":"OpenApiServlet's doPost performs the same principal assertion for POSTs to /openapi/*: authentication must have succeeded or the servlet refuses with this error (actually an NPE from calling getName() on a null principal). It signals the POST was not authenticated by Elytron.","triggerScenarios":"POST to /openapi/* without valid credentials or with a failed auth mechanism, making req.getUserPrincipal() null before .getName() is called.","commonSituations":"Missing Authorization header on POST; permissive auth policy for /openapi/*; elytron properties realm misconfigured; token/session expired mid-test.","solutions":["Send valid basic-auth credentials with the POST request.","Ensure quarkus.http.auth.permission policies require roles on /openapi/* POST and the realm is configured.","Verify security constraints run container-managed authentication before doPost.","Null-check getUserPrincipal() before calling getName()."],"exampleFix":"// before\nif (req.getUserPrincipal().getName() == null) {\n    throw new RuntimeException(\"principal was null\");\n}\n// after\nif (req.getUserPrincipal() == null) {\n    throw new RuntimeException(\"principal was null\");\n}","handlingStrategy":"try-catch","validationCode":"Response check = given().header(\"tenantId\", tenant).get(\"/fruits/\" + id);\nAssume.assumeFalse(check.getStatusCode() == 404);","typeGuard":null,"tryCatchPattern":"Response r = given().header(\"tenantId\", tenant).get(\"/fruits/\" + id);\nif (r.getStatusCode() == 404) {\n    // handle not-found: seed data or pick a valid id\n} else {\n    Fruit fruit = r.as(Fruit.class);\n}","preventionTips":["Seed MariaDB test data per tenant before assertions","Never reuse ids across environments or tenants","Assert status code before deserializing the body","Send the tenant header consistently (RestAssured filter helps)"],"tags":["servlet","security","openapi","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"}