HMCL-dev/HMCL · error · IllegalArgumentException

this.getClass() + " cannot be deserialized to " + type

Error message

this.getClass() + " cannot be deserialized to " + type

What it means

InstantTypeAdapter.deserialize parses a JSON string into an Instant, but only returns it when the requested target Type is exactly Instant.class. This IllegalArgumentException signals a configuration/misuse bug: this adapter was registered for a type it is not meant to handle.

Solutions

  1. Register the adapter only for Instant: gsonBuilder.registerTypeAdapter(Instant.class, new InstantTypeAdapter()).
  2. Ensure the field/TypeToken being deserialized is declared as java.time.Instant.
  3. Use a TypeToken<Instant> (not a raw or wildcard type) when calling fromJson.
  4. If another temporal type is intended, use the appropriate adapter for that type.

Example fix

// before
Gson g = new GsonBuilder().registerTypeAdapter(Object.class, new InstantTypeAdapter()).create();
// after
Gson g = new GsonBuilder().registerTypeAdapter(Instant.class, new InstantTypeAdapter()).create();
Defensive patterns

Strategy: type-guard

Validate before calling

if (targetType != Instant.class)
    throw new IllegalStateException("InstantTypeAdapter only supports Instant, got " + targetType);

Type guard

static <T> boolean supportsInstant(TypeToken<T> type) {
    return type.getRawType() == Instant.class;
}

Try / catch

try {
    return gson.fromJson(json, Instant.class);
} catch (IllegalArgumentException e) {
    log.error("Instant adapter misconfigured: {}", e.getMessage());
}

Prevention

When it happens

Trigger: Gson deserializing a JSON string where the target TypeToken is not Instant (e.g. LocalDateTime, OffsetDateTime) but this adapter is invoked, typically due to a wrong registerTypeAdapter or a wildcard/raw TypeToken.

Common situations: Registering InstantTypeAdapter for a broader type, using raw Gson without generics so type erasure routes the wrong target to the adapter, or changing a field's declared type from Instant to another temporal type without updating Gson setup.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


AI-assisted analysis of HMCL-dev/HMCL@24702dc5a0 (2026-09-10). Data as JSON: /api/errors/caecad5066b45509. Report an issue: GitHub.

Appendix: source

Thrown at HMCLCore/src/main/java/org/jackhuang/hmcl/util/gson/InstantTypeAdapter.java:73

        return new JsonPrimitive(serializeToString(t, ZoneId.systemDefault()));
    }

    /// Deserializes a JSON string into an [Instant].
    ///
    /// @param json    the JSON element to deserialize
    /// @param type    the requested target type
    /// @param context the Gson deserialization context
    /// @return the parsed instant
    /// @throws JsonParseException     if `json` is not a string or cannot be parsed as an instant
    /// @throws IllegalArgumentException if `type` is not [Instant]
    @Override
    public Instant deserialize(JsonElement json, Type type, JsonDeserializationContext context) throws JsonParseException {
        if (json instanceof JsonPrimitive) {
            Instant time = deserializeToInstant(json.getAsString());
            if (type == Instant.class)
                return time;
            else
                throw new IllegalArgumentException(this.getClass() + " cannot be deserialized to " + type);
        } else {
            throw new JsonParseException("The instant should be a string value");
        }
    }

    /// Formatter for the legacy US localized date-time representation.
    private static final DateTimeFormatter EN_US_FORMAT = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM, FormatStyle.MEDIUM)
            .withLocale(Locale.US)
            .withZone(ZoneId.systemDefault());

    /// Formatter for ISO local date-time text followed by one of the supported offset forms.
    private static final DateTimeFormatter ISO_DATE_TIME = new DateTimeFormatterBuilder()
            .append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
            .optionalStart().appendOffset("+HH:MM", "+00:00").optionalEnd()
            .optionalStart().appendOffset("+H:MM", "+0:00").optionalEnd()
            .optionalStart().appendOffset("+HHMM", "+0000").optionalEnd()
            .optionalStart().appendOffset("+HH", "Z").optionalEnd()
            .optionalStart().appendOffsetId().optionalEnd()

View on GitHub (pinned to 24702dc5a0)