apache/dolphinscheduler · error · IllegalArgumentException

Type reference cannot be null

Error message

Type reference cannot be null

What it means

JSONUtils.parseObject(String, TypeReference<T>) deserializes JSON into a generic type expressed via a Jackson TypeReference. It throws this IllegalArgumentException when the TypeReference argument is null — the type is required to drive deserialization. Note the argument-order guard: an empty/null json returns null before this check, but a present json with a null type throws.

Source

Thrown at dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/utils/JSONUtils.java:286

            return "";
        }
    }

    /**
     * json to object
     *
     * @param json json string
     * @param type type reference
     * @param <T>
     * @return return parse object
     */
    public static <T> T parseObject(String json, TypeReference<T> type) {
        if (Strings.isNullOrEmpty(json)) {
            return null;
        }

        if (type == null) {
            throw new IllegalArgumentException("Type reference cannot be null");
        }

        try {
            return objectMapper.readValue(json, type);
        } catch (Exception e) {
            throw new IllegalArgumentException("Parse json: " + json + " to type: " + type.getType() + " failed", e);
        }
    }

    /**
     * object to json string
     *
     * @param object object
     * @return json string
     */
    public static String toJsonString(Object object) {
        try {
            return objectMapper.writeValueAsString(object);

View on GitHub (pinned to 02eac45a1b)

Solutions

  1. Always pass an anonymous TypeReference literal: parseObject(json, new TypeReference<Map<String, Object>>() {}).
  2. Null-check/fail-fast the resolved TypeReference before calling, with a message naming the unresolved type.
  3. Fix the registry/switch that produces the TypeReference so all expected payload kinds are covered.
  4. Catch IllegalArgumentException around dynamic-type deserialization and return a typed failure.

Example fix

// before
TypeReference<List<Task>> ref = REF_CACHE.get(kind); // may be null
List<Task> tasks = JSONUtils.parseObject(json, ref);
// after
TypeReference<List<Task>> ref = REF_CACHE.get(kind);
if (ref == null) {
    ref = new TypeReference<List<Task>>() {}; // or throw new IllegalStateException("Unknown kind: " + kind);
}
List<Task> tasks = JSONUtils.parseObject(json, ref);
Defensive patterns

Strategy: type-guard

Validate before calling

Objects.requireNonNull(typeRef, "TypeReference for JSONUtils.parseObject must not be null");

Type guard

if (typeRef != null) {
    T value = JSONUtils.parseObject(json, typeRef);
}

Try / catch

try {
    return JSONUtils.parseObject(json, typeRef);
} catch (IllegalArgumentException e) {
    throw new IllegalStateException("TypeReference unresolved for payload", e);
}

Prevention

When it happens

Trigger: Calling parseObject(json, null) or passing a TypeReference<T> variable built conditionally (null when the type is unknown), e.g. parseObject(payload, refs.get(typeName)) where refs has no entry for typeName.

Common situations: Generic helper methods forwarding a TypeReference that wasn't initialized; a switch/registry of TypeReferences for polymorphic payloads missing a case; refactoring from the Class overload where the TypeReference was forgotten.

Related errors


AI-assisted analysis of apache/dolphinscheduler@02eac45a1b (2026-09-06). Data as JSON: /api/errors/41751d62bc985639. Report an issue: GitHub.