{"record":{"id":"caecad5066b45509","repo":"HMCL-dev/HMCL","slug":"this-getclass-cannot-be-deserialized-to","errorCode":null,"errorMessage":"this.getClass() + \" cannot be deserialized to \" + type","messagePattern":"this\\.getClass\\(\\) \\+ \" cannot be deserialized to \" \\+ type","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"HMCLCore/src/main/java/org/jackhuang/hmcl/util/gson/InstantTypeAdapter.java","lineNumber":73,"sourceCode":"        return new JsonPrimitive(serializeToString(t, ZoneId.systemDefault()));\n    }\n\n    /// Deserializes a JSON string into an [Instant].\n    ///\n    /// @param json    the JSON element to deserialize\n    /// @param type    the requested target type\n    /// @param context the Gson deserialization context\n    /// @return the parsed instant\n    /// @throws JsonParseException     if `json` is not a string or cannot be parsed as an instant\n    /// @throws IllegalArgumentException if `type` is not [Instant]\n    @Override\n    public Instant deserialize(JsonElement json, Type type, JsonDeserializationContext context) throws JsonParseException {\n        if (json instanceof JsonPrimitive) {\n            Instant time = deserializeToInstant(json.getAsString());\n            if (type == Instant.class)\n                return time;\n            else\n                throw new IllegalArgumentException(this.getClass() + \" cannot be deserialized to \" + type);\n        } else {\n            throw new JsonParseException(\"The instant should be a string value\");\n        }\n    }\n\n    /// Formatter for the legacy US localized date-time representation.\n    private static final DateTimeFormatter EN_US_FORMAT = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM, FormatStyle.MEDIUM)\n            .withLocale(Locale.US)\n            .withZone(ZoneId.systemDefault());\n\n    /// Formatter for ISO local date-time text followed by one of the supported offset forms.\n    private static final DateTimeFormatter ISO_DATE_TIME = new DateTimeFormatterBuilder()\n            .append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)\n            .optionalStart().appendOffset(\"+HH:MM\", \"+00:00\").optionalEnd()\n            .optionalStart().appendOffset(\"+H:MM\", \"+0:00\").optionalEnd()\n            .optionalStart().appendOffset(\"+HHMM\", \"+0000\").optionalEnd()\n            .optionalStart().appendOffset(\"+HH\", \"Z\").optionalEnd()\n            .optionalStart().appendOffsetId().optionalEnd()","sourceCodeStart":55,"sourceCodeEnd":91,"githubUrl":"https://github.com/HMCL-dev/HMCL/blob/24702dc5a0214034f4c27166d5fd30cad08cec19/HMCLCore/src/main/java/org/jackhuang/hmcl/util/gson/InstantTypeAdapter.java#L55-L91","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Register the adapter only for Instant: gsonBuilder.registerTypeAdapter(Instant.class, new InstantTypeAdapter()).","Ensure the field/TypeToken being deserialized is declared as java.time.Instant.","Use a TypeToken<Instant> (not a raw or wildcard type) when calling fromJson.","If another temporal type is intended, use the appropriate adapter for that type."],"exampleFix":"// before\nGson g = new GsonBuilder().registerTypeAdapter(Object.class, new InstantTypeAdapter()).create();\n// after\nGson g = new GsonBuilder().registerTypeAdapter(Instant.class, new InstantTypeAdapter()).create();","handlingStrategy":"type-guard","validationCode":"if (targetType != Instant.class)\n    throw new IllegalStateException(\"InstantTypeAdapter only supports Instant, got \" + targetType);","typeGuard":"static <T> boolean supportsInstant(TypeToken<T> type) {\n    return type.getRawType() == Instant.class;\n}","tryCatchPattern":"try {\n    return gson.fromJson(json, Instant.class);\n} catch (IllegalArgumentException e) {\n    log.error(\"Instant adapter misconfigured: {}\", e.getMessage());\n}","preventionTips":["Register temporal adapters with exact types (registerTypeAdapter(Instant.class, ...)).","Avoid raw Gson TypeTokens that erase the target type.","Keep field declarations and adapter registrations in sync."],"tags":["gson","deserialization","type-mismatch"],"backgroundTag":"type-mismatch","analyzedSha":"24702dc5a0214034f4c27166d5fd30cad08cec19","analyzedAt":"2026-09-10T12:36:46.680Z","contentChangedAt":"2026-09-10T12:36:46.680Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}