{"record":{"id":"fcc2fe63d4d81260","repo":"quarkusio/quarkus","slug":"expression-is-not-a-literal","errorCode":null,"errorMessage":"Expression is not a literal: ","messagePattern":"Expression is not a literal: ","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"independent-projects/qute/core/src/main/java/io/quarkus/qute/ExpressionImpl.java","lineNumber":95,"sourceCode":"\n    @Override\n    public boolean isLiteral() {\n        return literal != null && parts.size() <= 1;\n    }\n\n    public CompletableFuture<Object> getLiteralValue() {\n        return literal != null ? literal.toCompletableFuture() : null;\n    }\n\n    @Override\n    public Object getLiteral() {\n        return literal != null ? literal.get() : null;\n    }\n\n    @Override\n    public CompletionStage<Object> asLiteral() {\n        if (literal == null) {\n            throw new IllegalStateException(\"Expression is not a literal: \" + toString());\n        }\n        return literal;\n    }\n\n    public Origin getOrigin() {\n        return origin;\n    }\n\n    @Override\n    public int getGeneratedId() {\n        return id;\n    }\n\n    @Override\n    public int hashCode() {\n        final int prime = 31;\n        int result = 1;\n        result = prime * result + Objects.hashCode(toOriginalString());","sourceCodeStart":77,"sourceCodeEnd":113,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/independent-projects/qute/core/src/main/java/io/quarkus/qute/ExpressionImpl.java#L77-L113","documentation":"asLiteral() returns the pre-evaluated literal value of a literal expression as a CompletionStage. It throws IllegalStateException when the ExpressionImpl was not constructed as a literal (literal field is null), meaning the expression is dynamic or a part-based expression that has no cached literal value.","triggerScenarios":"Calling asLiteral() on an expression created via parts (e.g. from a normal template expression like {name}) rather than via literal()/literalFrom().","commonSituations":"Extension or custom resolver code that assumes an expression is a constant and calls asLiteral() on user-supplied template expressions that turn out to be dynamic (contain method calls, properties, etc.).","solutions":["Guard with expression.isLiteral() (or check the literal field) before calling asLiteral().","Fall back to evaluating the expression through the resolution context when it is not a literal.","Inspect the template expression origin to confirm it was created as a literal."],"exampleFix":"// before\nObject v = expr.asLiteral().toCompletableFuture().join();\n// after\nif (expr.isLiteral()) {\n    Object v = expr.asLiteral().toCompletableFuture().join();\n} else {\n    Object v = expr.eval(resolutionContext).toCompletableFuture().join();\n}","handlingStrategy":"type-guard","validationCode":"if (expr == null || !expr.isLiteral()) {\n    // not usable as literal — evaluate dynamically instead\n}","typeGuard":"boolean isLiteralExpr(Expression e) {\n    return e instanceof ExpressionImpl impl && impl.isLiteral();\n}","tryCatchPattern":"try {\n    return expr.asLiteral().toCompletableFuture().join();\n} catch (IllegalStateException ex) {\n    return expr.eval(ctx).toCompletableFuture().join(); // dynamic fallback\n}","preventionTips":["Only call asLiteral() on expressions you created via literal()/literalFrom()","Check isLiteral() before treating an expression as constant","Prefer full evaluation for user-authored template expressions"],"tags":["qute","template","illegal-state","not-a-literal"],"backgroundTag":"invalid-state-api-misuse","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}