{"record":{"id":"cac24ee8e75d30c7","repo":"oracle/graal","slug":"compilationfinal-dimensions-d-exceeds-declared","errorCode":null,"errorMessage":"@CompilationFinal(dimensions=%d) exceeds declared array dimensions (%d) of field %s","messagePattern":"@CompilationFinal\\(dimensions=(.+?)\\) exceeds declared array dimensions \\((.+?)\\) of field (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/PartialEvaluator.java","lineNumber":169,"sourceCode":"        for (JavaType componentType = type; componentType.isArray(); componentType = componentType.getComponentType()) {\n            dimensions++;\n        }\n        return dimensions;\n    }\n\n    private static int actualStableDimensions(ResolvedJavaField field, int dimensions) {\n        if (dimensions == 0) {\n            return 0;\n        }\n        int arrayDim = getArrayDimensions(field.getType());\n        if (dimensions < 0) {\n            if (dimensions != -1) {\n                throw new IllegalArgumentException(\"Negative @CompilationFinal dimensions\");\n            }\n            return arrayDim;\n        }\n        if (dimensions > arrayDim) {\n            throw new IllegalArgumentException(String.format(\"@CompilationFinal(dimensions=%d) exceeds declared array dimensions (%d) of field %s\", dimensions, arrayDim, field));\n        }\n        return dimensions;\n    }\n\n    /**\n     * Gets an object describing how a read of {@code field} can be constant folded based on Truffle\n     * annotations.\n     *\n     * @param field the field for which to compute {@link ConstantFieldInfo}\n     * @param declaredAnnotationValues a map of method annotations keyed by their declaring\n     *            {@link ResolvedJavaType}\n     * @param types cached types known to the Truffle compiler\n     * @param unwrapType a function that unwraps a {@link ResolvedJavaType} obtained from\n     *            {@code types} to its underlying host {@link ResolvedJavaType}. In native-image,\n     *            known Truffle types are represented as {@code AnalysisType}, while the keys in\n     *            {@code declaredAnnotationValues} correspond to host JVMCI types. Therefore, each\n     *            {@code AnalysisType} must be unwrapped via\n     *            {@code OriginalClassProvider.getOriginalType(JavaType)} to correctly access the","sourceCodeStart":151,"sourceCodeEnd":187,"githubUrl":"https://github.com/oracle/graal/blob/a66e9ccd1d7bf2552883939aa0788dfd0e294aab/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/PartialEvaluator.java#L151-L187","documentation":"The second @CompilationFinal validation in actualStableDimensions: for a non-negative dimensions value, it counts the array dimensions of the field's declared type (getArrayDimensions) and throws IllegalArgumentException when dimensions exceeds that count. The annotation claims more stable array levels than the field's type actually has.","triggerScenarios":"@CompilationFinal(dimensions = 2) on a field of type Object[] (1 dimension), or any positive dimensions on a non-array field.","commonSituations":"Changing a field's type from Object[][] to Object[] or to a scalar without updating the annotation; copy-pasting an annotated field declaration and changing only the type.","solutions":["Lower dimensions to at most the array depth of the field's type (0 for scalar fields, which means the reference itself is stable).","Or change the field type to an array with at least that many dimensions if deeper stability was intended."],"exampleFix":"// before\n@CompilationFinal(dimensions = 2)\nObject[] values; // only 1 array dimension\n\n// after\n@CompilationFinal(dimensions = 1)\nObject[] values;","handlingStrategy":"validation","validationCode":"// Mirror the compiler's check: annotation dimensions must not exceed the field's array depth\nstatic void checkCompilationFinal(Class<?> owner, String fieldName, int dimensions) throws NoSuchFieldException {\n    Class<?> t = owner.getDeclaredField(fieldName).getType();\n    int arrayDim = 0;\n    while (t.isArray()) { arrayDim++; t = t.getComponentType(); }\n    if (dimensions < -1 || (dimensions >= 0 && dimensions > arrayDim)) {\n        throw new IllegalArgumentException(owner.getName() + \".\" + fieldName\n                + \": dimensions=\" + dimensions + \" exceeds array depth \" + arrayDim);\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Whenever you change the type of a @CompilationFinal field, re-check its dimensions attribute against the new array depth.","Add a reflection-based build/test check (as above) that walks all @CompilationFinal fields and validates their dimensions."],"tags":["graal","truffle","compilation-final","annotation","array-dimensions"],"backgroundTag":null,"analyzedSha":"a66e9ccd1d7bf2552883939aa0788dfd0e294aab","analyzedAt":"2026-08-14T13:58:47.161Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}