{"record":{"id":"5bf3459d98884416","repo":"oracle/graal","slug":"could-not-unwrap-a-primitive-array-constant","errorCode":null,"errorMessage":"Could not unwrap a primitive array constant: {}","messagePattern":"Could not unwrap a primitive array constant: (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"compiler/src/jdk.graal.compiler.hostvmaccess/src/jdk/graal/compiler/hostvmaccess/HostVMAccess.java","lineNumber":308,"sourceCode":"     */\n    @Override\n    public JavaConstant createPrimitiveArray(JavaKind kind, int length) {\n        if (kind == null || !kind.isPrimitive() || kind == JavaKind.Void) {\n            throw new IllegalArgumentException(\"Expected a non-void primitive kind, got \" + kind);\n        }\n        Object array = Array.newInstance(kind.toJavaClass(), length);\n        return providers.getSnippetReflection().forObject(array);\n    }\n\n    @Override\n    public JavaConstant clonePrimitiveArray(JavaConstant primitiveArray) {\n        ResolvedJavaType arrayType = getProviders().getMetaAccess().lookupJavaType(primitiveArray);\n        if (arrayType == null || !arrayType.isArray() || !arrayType.getComponentType().isPrimitive()) {\n            throw new IllegalArgumentException(\"Expected a primitive array constant, got \" + primitiveArray);\n        }\n        Object source = providers.getSnippetReflection().asObject(Object.class, primitiveArray);\n        if (source == null) {\n            throw new IllegalArgumentException(\"Could not unwrap a primitive array constant: \" + primitiveArray);\n        }\n        /*\n         * Keep cloning explicit by primitive array kind. This avoids reflective clone access and\n         * preserves exact array runtime type through each typed clone() call.\n         */\n        Object copy = switch (source) {\n            case boolean[] array -> array.clone();\n            case byte[] array -> array.clone();\n            case short[] array -> array.clone();\n            case char[] array -> array.clone();\n            case int[] array -> array.clone();\n            case long[] array -> array.clone();\n            case float[] array -> array.clone();\n            case double[] array -> array.clone();\n            default -> throw new IllegalArgumentException(\"Expected a primitive array constant, got \" + primitiveArray);\n        };\n        return providers.getSnippetReflection().forObject(copy);\n    }","sourceCodeStart":290,"sourceCodeEnd":326,"githubUrl":"https://github.com/oracle/graal/blob/a66e9ccd1d7bf2552883939aa0788dfd0e294aab/compiler/src/jdk.graal.compiler.hostvmaccess/src/jdk/graal/compiler/hostvmaccess/HostVMAccess.java#L290-L326","documentation":"Thrown by HostVMAccess.clonePrimitiveArray when the constant passed the type guard (it types as a primitive array) but SnippetReflectionProvider.asObject(Object.class, primitiveArray) returns null, so the actual array object cannot be retrieved for cloning. It separates 'wrong kind of constant' (previous error) from 'unwrappable constant'.","triggerScenarios":"Calling clonePrimitiveArray with a constant that is statically typed as a primitive array but is not backed by a live host object — e.g. a synthesized/embedded constant (from Content-level data such as an image-heap constant) that snippet reflection cannot map to an Object.","commonSituations":"Constants obtained from serialized/deserialized compilation data or a different snippet reflection instance losing the object mapping; hotswap/substitution producing synthetic array constants; unwrapping after the underlying object was garbage or the provider context changed between runs.","solutions":["Re-materialize the array as a host object first (e.g. rebuild it from the constant's elements via asArrayConstant) and clone that","Ensure the constant was created by the same SnippetReflectionProvider instance you are unwrapping with","For embedded/image constants, extract elements and reconstruct instead of relying on asObject"],"exampleFix":"// before\nJavaConstant copy = hostVM.clonePrimitiveArray(embeddedConstant);  // types OK but asObject -> null -> throws\n\n// after\n// rebuild a live array constant in this provider context, then clone\nJavaConstant live = hostVM.asArrayConstant(componentType, elementsOf(embeddedConstant));\nJavaConstant copy = hostVM.clonePrimitiveArray(live);","handlingStrategy":"validation","validationCode":"Object probe = snippetReflection.asObject(Object.class, constant);\nif (probe == null) { /* rematerialize via asArrayConstant instead of cloning */ }","typeGuard":"static boolean isLiveHostObject(JavaConstant c, SnippetReflectionProvider s) { return s.asObject(Object.class, c) != null; }","tryCatchPattern":"catch (IllegalArgumentException e) { rebuild the array from elements (asArrayConstant) and clone the result }","preventionTips":["Use one SnippetReflectionProvider instance for create and unwrap","Rematerialize embedded/deserialized constants before host operations","Treat unwrappable constants as data, not live objects"],"tags":["graalvm","hostvmaccess","arrays","constants"],"backgroundTag":null,"analyzedSha":"a66e9ccd1d7bf2552883939aa0788dfd0e294aab","analyzedAt":"2026-08-14T13:58:47.161Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}