{"record":{"id":"ad19eeb2d796bee4","repo":"oracle/graal","slug":"both-value-and-type-are-specified-for-espress","errorCode":null,"errorMessage":"Both 'value' and 'type' are specified for @EspressoSubstitution {className}","messagePattern":"Both 'value' and 'type' are specified for @EspressoSubstitution (.+?)","errorType":"exception","errorClass":"AssertionError","httpStatus":null,"severity":"error","filePath":"espresso/src/com.oracle.truffle.espresso.processor/src/com/oracle/truffle/espresso/processor/SubstitutionProcessor.java","lineNumber":195,"sourceCode":"            targetClassName = \"L\" + className.substring(\"Target_\".length()).replace(\"_\", \"/\") + \";\";\n        }\n        int successfulScheme = 0;\n        // If it exists, collect the value of EspressoSubstitutions.value()\n        TypeMirror targetClass = getAnnotationValue(annotation, \"value\", TypeMirror.class);\n        assert targetClass != null; // Default value is EspressoSubstitutions.class\n        // If it exists, collect the value of EspressoSubstitutions.type()\n        String targetType = getAnnotationValue(annotation, \"type\", String.class);\n\n        if (!processingEnv.getTypeUtils().isSameType(targetClass, espressoSubstitutions.asType())) {\n            targetClassName = \"L\" + targetClass.toString().replace(\".\", \"/\") + \";\";\n            successfulScheme++;\n        }\n        if (targetType != null && !targetType.isEmpty()) {\n            targetClassName = targetType;\n            successfulScheme++;\n        }\n        if (successfulScheme > 1) {\n            throw new AssertionError(\"Both 'value' and 'type' are specified for @EspressoSubstitution \" + className);\n        }\n\n        // Get the name provider. Will override the previously obtained target class name.\n        TypeMirror defaultNameProvider = getNameProvider(annotation);\n\n        // Thr group to be used for the @Collect annotation\n        TypeMirror group = getAnnotationValue(annotation, \"group\", TypeMirror.class);\n\n        for (Element element : substitution.getEnclosedElements()) {\n            processSubstitution(element, className, defaultNameProvider, targetClassName, typeElement, group);\n        }\n    }\n\n    private void checkParameterOrReturnType(String headerMessage, TypeMirror typeMirror, Element element, boolean allowPointerType) {\n        if (typeMirror.getKind().isPrimitive()) {\n            if (getAnnotation(typeMirror, javaType) != null) {\n                processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,\n                                headerMessage + \" (primitive type) cannot be annotated with @JavaType\", element);","sourceCodeStart":177,"sourceCodeEnd":213,"githubUrl":"https://github.com/oracle/graal/blob/a66e9ccd1d7bf2552883939aa0788dfd0e294aab/espresso/src/com.oracle.truffle.espresso.processor/src/com/oracle/truffle/espresso/processor/SubstitutionProcessor.java#L177-L213","documentation":"AssertionError from the EspressoSubstitution annotation processor at compile time: a single @EspressoSubstitution annotation specified both the class member ('value') and the 'type' string. The processor counts successful target-resolution schemes and refuses ambiguity when more than one is set.","triggerScenarios":"Writing @EspressoSubstitution(value = MyClass.class, type = \"com/example/MyClass\") on the same substitution; adding a 'type' attribute to an existing annotation that already names a class; copy-pasting a template that fills in both attributes.","commonSituations":"Annotating a class whose target is not on the annotation-processor classpath, then also adding type= as a workaround; upgrading Espresso versions where templates/examples changed; IDE auto-completing both attributes.","solutions":["Remove one of the two attributes: keep 'value' when the target class is visible at compile time, otherwise keep only 'type'.","If the class is not on the processor classpath, use type = \"Lcom/example/MyClass;\" exclusively.","Rebuild so the annotation processor re-runs and confirms the error is gone."],"exampleFix":"// before\n@EspressoSubstitution(value = ArrayList.class, type = \"java/util/ArrayList\")\nstatic class MySubstitution { ... }\n\n// after\n@EspressoSubstitution(value = ArrayList.class)\nstatic class MySubstitution { ... }","handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":["Set exactly one of 'value' or 'type' per @EspressoSubstitution annotation.","Use 'type' only when the target class is unavailable to the annotation processor.","Fix annotation-processor errors immediately; they break the whole compilation."],"tags":["annotation-processing","compile-time","espresso","substitution","configuration"],"backgroundTag":null,"analyzedSha":"a66e9ccd1d7bf2552883939aa0788dfd0e294aab","analyzedAt":"2026-08-14T13:58:47.161Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}