stanfordnlp/CoreNLP · error · IllegalStateException

Unhandled primitive type in array

Error message

Unhandled primitive type in array: ${componentType}

What it means

JSONOutputter's routeObject converts annotation values into JSON. It handles primitive arrays (int[], double[], boolean[], etc.) explicitly; when the array's component type is a primitive it does not handle (e.g. short[], char[], byte[], float[], long[]), an IllegalStateException is thrown because there is no conversion path.

Solutions

  1. Convert unsupported primitive arrays to List< boxedType > or the supported type (int[]/double[]/boolean[]) before passing to JSONOutputter
  2. Box the array manually (e.g. ArrayUtils.toObject or a loop into ArrayList<Long>)
  3. Change the annotator to store the value as a boxed array (Long[]/Float[]) or List so the Object[] branch handles it
  4. If this is a CoreNLP bug, file/patch the missing primitive branch in routeObject

Example fix

// before
annotations.put(CoreAnnotations.MyStats.class, new long[]{1L, 2L});
// after
annotations.put(CoreAnnotations.MyStats.class, new long[]{1L, 2L});
// ...and before outputting:
List<Long> boxed = Arrays.stream(longs).boxed().collect(Collectors.toList());
Defensive patterns

Strategy: type-guard

Validate before calling

Object v = ann.get(key);
Class<?> c = v.getClass();
if (c.isArray() && c.getComponentType().isPrimitive()
    && !(c == int[].class || c == double[].class || c == boolean[].class))
  throw new IllegalArgumentException("Unsupported primitive array for JSON: " + c);

Type guard

static boolean isJsonSafeArray(Object v) {
  Class<?> c = v.getClass();
  if (!c.isArray() || !c.getComponentType().isPrimitive()) return true;
  return c == int[].class || c == double[].class || c == boolean[].class;
}

Try / catch

try {
  JSONOutputter.jsonPrint(writer, annotation);
} catch (IllegalStateException e) {
  if (e.getMessage().startsWith("Unhandled primitive type in array")) {
    // box the array or convert to List before re-serializing
  } else throw e;
}

Prevention

When it happens

Trigger: Passing a map/annotation value that is a primitive array of a type other than int/double/boolean — e.g. a long[], short[], char[], byte[], or float[] — into JSONOutputter's write/output path.

Common situations: Custom Annotator keys storing long[] or float[] statistics arrays; utility code that boxes most values but stores raw primitive arrays of less-common types; passing NLP feature vectors stored as byte[] or short[].

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of stanfordnlp/CoreNLP@1b7edd19c4 (2026-09-10). Data as JSON: /api/errors/511ef39577bdc488. Report an issue: GitHub.

Appendix: source

Thrown at src/edu/stanford/nlp/pipeline/JSONOutputter.java:520

            for (float elem : ((float[]) value)) {
              lst.add(elem);
            }
            routeObject(indent, lst);
          } else if (double.class.isAssignableFrom(componentType)) {
            ArrayList<Double> lst = new ArrayList<>();
            //noinspection Convert2streamapi
            for (double elem : ((double[]) value)) {
              lst.add(elem);
            }
            routeObject(indent, lst);
          } else if (boolean.class.isAssignableFrom(componentType)) {
            ArrayList<Boolean> lst = new ArrayList<>();
            for (boolean elem : ((boolean[]) value)) {
              lst.add(elem);
            }
            routeObject(indent, lst);
          } else {
            throw new IllegalStateException("Unhandled primitive type in array: " + componentType);
          }
        } else {
          routeObject(indent, Arrays.asList((Object[]) value));
        }
      } else if (value instanceof Integer) {
        writer.write(Integer.toString((Integer) value));
      } else if (value instanceof Short) {
        writer.write(Short.toString((Short) value));
      } else if (value instanceof Byte) {
        writer.write(Byte.toString((Byte) value));
      } else if (value instanceof Long) {
        writer.write(Long.toString((Long) value));
      } else if (value instanceof Character) {
        writer.write(Character.toString((Character) value));
      } else if (value instanceof Float) {
        // Use the US Locale so that we can conform with json output format
        // The decimal separator is always supposed to be . for example
        Locale locale = Locale.US;

View on GitHub (pinned to 1b7edd19c4)