ArrayStoreException is an unchecked exception that the JVM throws when code stores a value in an array whose runtime element type cannot hold it, for example an Integer in an array created as String[]. The code compiles, because the variable has a wider type such as Object[], and the error shows up only when the store runs.
We meet the exception in code that passes arrays around as Object[] or Number[], and in JDK methods that store elements for us, such as System.arraycopy() and toArray(). The fix is almost always a type change, not a try-catch block.
The following example compiles without a warning and fails on the third line.
Object[] labels = new String[2]; // compiles, arrays are covariant
labels[0] = "draft"; // fine, a String
labels[1] = 42; // ArrayStoreException: java.lang.Integer
Notice that the declared type Object[] accepts 42, but the array object is a String[]. We look at why Java allows the assignment, what the messages mean, the real-world sources of the exception, and the fixes.
1. Why the Compiler Lets the Bad Store Through
Java arrays are covariant. If String is a subtype of Object, the JLS makes String[] a subtype of Object[], so an Object[] variable can point to a String[]. The compiler checks every store against the variable’s type, and for an Object[] variable any object passes.
![An Object[] variable pointing to a String[] array; storing a String passes the runtime check and storing an Integer throws ArrayStoreException](https://howtodoinjava.com/wp-content/uploads/2026/10/java-arraystoreexception-covariant-array.png)
The array object itself remembers its element type. On every store into an array of references, the JVM checks that the value fits that type, and if it does not, it throws ArrayStoreException before the array changes. A null value always passes, because null fits every reference type.
Integer[] ids = {1, 2};
Number[] numbers = ids; // legal, Integer[] is a Number[]
numbers[0] = 7; // fine, an Integer
numbers[1] = 2.5; // ArrayStoreException: java.lang.Double
Object[] names = new String[1];
names[0] = null; // fine, null fits any reference type
Generics are invariant, so the same mistake with a List fails at compile time instead of at runtime. A List<String> is not a List<Object>, which is one reason to prefer collections over arrays in APIs, as the Java generics guide explains.
// does not compile: incompatible types: List<String> cannot be converted to List<Object>
List<Object> labels = new ArrayList<String>();
2. Reading the Exception Message
The message names the class of the value that did not fit, so java.lang.ArrayStoreException: java.lang.Double means some code tried to store a Double. The first line of the stack trace points to the store. To find the real cause, we look for the place where the array was created with a narrower type than the variable suggests.
System.arraycopy() uses longer messages that describe the two arrays. HotSpot on Java 25 prints these texts for the three typical cases.
java.lang.ArrayStoreException: arraycopy: type mismatch: can not copy int[] into long[]
java.lang.ArrayStoreException: arraycopy: type mismatch: can not copy int[] into object array[]
java.lang.ArrayStoreException: arraycopy: element type mismatch: can not cast one of the elements of java.lang.Object[] to the type of the destination array, java.lang.String
The wording of these messages comes from the JVM and is not part of the API, so we do not parse it in code. The exception type and the stack trace are what we act on.
3. Where ArrayStoreException Comes From in Real Code
Direct stores such as labels[1] = 42 are rare in production code. The exception mostly comes from library calls that store elements for us.
3.1. Methods That Take Object[] Parameters
Say a form library has a helper that fills empty slots with a placeholder. It takes an Object[] so it works with any array, and it stores an Integer 0. Called with an Integer[], it works, but a caller that passes a String[] gets the exception from inside the library.
static void fillBlanks(Object[] slots) {
for (int i = 0; i < slots.length; i++) {
if (slots[i] == null) {
slots[i] = 0;
}
}
}
Integer[] counts = {5, null};
fillBlanks(counts);
Integer[] filled = counts; // [5, 0]
String[] fields = {"name", null};
fillBlanks(fields); // ArrayStoreException: java.lang.Integer
Arrays.fill() has the same Object[] signature, so Arrays.fill(stringArrayAsObjects, 0) fails the same way.
3.2. System.arraycopy() Between Incompatible Arrays
The System.arraycopy() method takes its arrays as Object, so the compiler cannot check them. It throws ArrayStoreException for a primitive source and a reference destination, for two different primitive types, and for a reference element that does not fit the destination.
int[] raw = {1, 2};
long[] wide = new long[2];
System.arraycopy(raw, 0, wide, 0, 2); // ArrayStoreException: arraycopy: type mismatch
Object[] mixed = {"a", "b", 3, "d"};
String[] dest = new String[4];
System.arraycopy(mixed, 0, dest, 0, 4); // ArrayStoreException: arraycopy: element type mismatch
String[] partial = dest; // [a, b, null, null]
The last line shows a detail from the Javadoc. In the element-by-element case, the elements before the bad one are already copied, so the destination array is left half-filled. Code that retries the copy must reset or discard the destination array.
3.3. toArray() on Collections and Streams
Collection.toArray(T[]) and Stream.toArray(generator) create an array of the type we ask for and store every element in it. A List<Object> or a raw list filled from JSON or a database can contain a different type than we expect, and the conversion fails.
List<Object> row = new ArrayList<>(List.of("Lokesh", 37));
String[] cells = row.toArray(new String[0]); // ArrayStoreException
String[] values = Stream.of((Object) "a", 2).toArray(String[]::new); // ArrayStoreException: java.lang.Integer
The safe version maps every element to the target type first, so a wrong value fails with a clear message, or it is converted on purpose. The guide on converting a List to an array covers the normal case.
List<Object> row = new ArrayList<>(List.of("Lokesh", 37));
String[] cells = row.stream().map(String::valueOf).toArray(String[]::new); // [Lokesh, 37]
3.4. Arrays.copyOf() With a Different Array Type
The overload Arrays.copyOf(original, length, newType) copies an array into a new array of another type. Every element must fit the new element type, otherwise the method throws.
Object[] input = {"a", 1};
Object[] asStrings = Arrays.copyOf(input, 2, String[].class); // ArrayStoreException
Object[] ok = Arrays.copyOf(new Object[] {"a", "b"}, 2, String[].class);
String type = ok.getClass().getSimpleName(); // "String[]"
4. Fixing and Preventing ArrayStoreException
The real fix is to make the array’s element type match the values we store, so the exception cannot happen. In order of preference, we do the following.
- Declare the variable with the exact array type, such as String[] instead of Object[], so the compiler rejects wrong stores.
- Use a List<T> in method parameters and return types, because generics catch the mismatch at compile time.
- Convert values to the target type before a toArray() call, as in section 3.
- Create the array with the element type that the values need, for example Object[] when the values are mixed.
When a method must accept arrays of unknown type, it can check each value before the store. The check uses Class.isInstance(), which also accepts subtypes, whereas comparing getClass() with == rejects a subtype such as an Integer in a Number[].
static boolean tryStore(Object[] array, int index, Object value) {
Class<?> elementType = array.getClass().getComponentType();
if (value != null && !elementType.isInstance(value)) {
return false;
}
array[index] = value;
return true;
}
Number[] amounts = new Integer[2];
boolean stored = tryStore(amounts, 0, 10); // true
boolean rejected = tryStore(amounts, 1, 9.99); // false, a Double does not fit
Number[] result = amounts; // [10, null]
Catching ArrayStoreException is a last resort for code that receives arrays from plugins or reflection. A catch block hides the type mistake and leaves the array partly updated in the arraycopy() case, so we log it with the array type and fix the caller.
5. ArrayStoreException Compared With Similar Exceptions
ArrayStoreException extends RuntimeException and has existed since Java 1.0. Developers often confuse it with other runtime exceptions that involve arrays or types.
| Exception | Thrown when | Example |
|---|---|---|
| ArrayStoreException | A value does not fit the array’s runtime element type | objs[0] = 1 where objs is a String[] |
| ClassCastException | A cast names a type the object does not have | (String) Integer.valueOf(1) |
| ArrayIndexOutOfBoundsException | The index is negative or not less than length | two[2] where two has length 2 |
| NegativeArraySizeException | An array is created with a negative length | new int[-1] |
Object value = Integer.valueOf(1);
String text = (String) value; // ClassCastException
int[] two = new int[2];
int third = two[2]; // ArrayIndexOutOfBoundsException
6. ArrayStoreException FAQs
Most questions about ArrayStoreException come from the gap between the compile-time check on the variable type and the runtime check on the array type.
6.1. Is ArrayStoreException checked or unchecked?
Unchecked. It extends RuntimeException, so methods do not declare it and the compiler does not force us to catch it.
6.2. Can ArrayStoreException happen with primitive arrays?
Not with normal stores, because the compiler rejects a double stored into an int[] without a cast. It happens only through System.arraycopy() between different primitive types, or between a primitive and a reference array.
6.3. Why do generics not throw ArrayStoreException?
Because generic types are invariant and checked at compile time, so a List<Object> variable cannot point to a List<String>. For the same reason, Java does not allow new T[] or new List<String>[10], since the runtime store check could not see the type argument.
6.4. Does Arrays.asList(array).toArray() still cause ArrayStoreException?
Not since Java 9. Before Java 9, Arrays.asList(stringArray).toArray() returned a String[] instead of an Object[] (JDK-6260652), so storing another type in the result threw. Since Java 9 the method returns an Object[].
6.5. Should we catch ArrayStoreException?
Rarely. The exception signals a type bug in our code, and the fix is a correct array or a List. We catch it only at a boundary that receives arrays we do not control, and we log the array type there.
7. Conclusion
ArrayStoreException comes from array covariance. A String[] can sit in an Object[] variable, so the compiler accepts any object, and the JVM rejects the store at runtime with the class name of the wrong value.
In real code, the exception comes from helpers with Object[] parameters, System.arraycopy(), toArray() calls and Arrays.copyOf() with a new type. Exact array types and List<T> move the check to compile time, and Class.isInstance() guards the rare code that must accept any array.
8. References
- ArrayStoreException (Java SE 25 API)
- System.arraycopy() (Java SE 25 API)
- JLS 25, Array Store Exception
- JLS 25, Subtyping among Array Types
Happy Learning !!