{"record":{"id":"0524d26eb4a37d22","repo":"HMCL-dev/HMCL","slug":"unsupported-field-type","errorCode":null,"errorMessage":"Unsupported field type: ","messagePattern":"Unsupported field type: ","errorType":"exception","errorClass":"JsonParseException","httpStatus":null,"severity":"error","filePath":"HMCLCore/src/main/java/org/jackhuang/hmcl/util/gson/ObservableSetting.java","lineNumber":306,"sourceCode":"\n            @SuppressWarnings({\"unchecked\"})\n            @Override\n            public void deserialize(T value, JsonElement element, JsonDeserializationContext context) {\n                List<?> deserialized = context.deserialize(element, listType);\n                Object fieldValue = get(value);\n\n                if (fieldValue instanceof ListProperty) {\n                    ((ListProperty<Object>) fieldValue).set(FXCollections.observableList((List<Object>) deserialized));\n                } else if (fieldValue instanceof ObservableList) {\n                    ((ObservableList<Object>) fieldValue).setAll(deserialized);\n                } else if (fieldValue instanceof SetProperty) {\n                    ((SetProperty<Object>) fieldValue).set(FXCollections.observableSet(new HashSet<>(deserialized)));\n                } else if (fieldValue instanceof ObservableSet) {\n                    ObservableSet<Object> set = (ObservableSet<Object>) fieldValue;\n                    set.clear();\n                    set.addAll(deserialized);\n                } else {\n                    throw new JsonParseException(\"Unsupported field type: \" + fieldValue.getClass());\n                }\n            }\n        }\n\n        private static final class MapField<T> extends ObservableField<T> {\n            private final Type mapType;\n\n            MapField(String serializedName, List<String> alternate, VarHandle varHandle, Type mapType) {\n                super(serializedName, alternate, varHandle);\n                this.mapType = mapType;\n            }\n\n            @Override\n            public void serialize(JsonObject result, T value, JsonSerializationContext context) {\n                result.add(getSerializedName(), context.serialize(get(value), mapType));\n            }\n\n            @SuppressWarnings({\"unchecked\"})","sourceCodeStart":288,"sourceCodeEnd":324,"githubUrl":"https://github.com/HMCL-dev/HMCL/blob/24702dc5a0214034f4c27166d5fd30cad08cec19/HMCLCore/src/main/java/org/jackhuang/hmcl/util/gson/ObservableSetting.java#L288-L324","documentation":"ObservableSetting's field deserializer copies deserialized values into JavaFX observable properties (ListProperty/MapProperty/SetProperty or plain Observable collections). This JsonParseException is thrown when a field's runtime value is an observable type the code does not support.","triggerScenarios":"Restoring settings from JSON when a field's value is an Observable* subtype that is not a List/Map/Set property handled by the if/else chain (e.g. a new custom ObservableValue or BooleanProperty added to settings).","commonSituations":"Adding a new setting field of an unsupported observable type without updating the deserializer; version drift where a config written by a newer HMCL contains a field type this build cannot restore.","solutions":["Change the setting field to a supported type: ObservableList/ObservableMap/ObservableSet or the corresponding *Property.","Extend the deserializer's if/else chain to handle the new observable field type.","If this error appears after a version change, update HMCL to a build that supports the field type.","Remove or rename the offending field in the persisted settings JSON to skip it."],"exampleFix":"// before\nprivate final StringProperty name = new SimpleStringProperty(); // unsupported by this branch\n// after\nprivate final ObservableList<String> items = FXCollections.observableArrayList(); // supported","handlingStrategy":"type-guard","validationCode":"if (!(fieldValue instanceof ObservableList\n        || fieldValue instanceof ObservableMap\n        || fieldValue instanceof ObservableSet\n        || fieldValue instanceof SetProperty))\n    throw new IllegalArgumentException(\"Unsupported observable field: \" + fieldValue.getClass());","typeGuard":"static boolean isSupportedObservableField(Object v) {\n    return v instanceof ObservableList || v instanceof ObservableMap || v instanceof ObservableSet || v instanceof SetProperty;\n}","tryCatchPattern":"try {\n    restoreSettings(json);\n} catch (JsonParseException e) {\n    log.error(\"Settings field type unsupported: {}\", e.getMessage(), e);\n}","preventionTips":["Use only ObservableList/Map/Set (or their *Property wrappers) for settings fields.","Update the deserializer's type chain whenever adding a new observable field type.","Test config round-trips after adding settings fields.","Keep HMCL versions in sync with the config format that wrote the file."],"tags":["gson","javafx","deserialization","unsupported-type"],"backgroundTag":"unsupported-operation","analyzedSha":"24702dc5a0214034f4c27166d5fd30cad08cec19","analyzedAt":"2026-09-10T12:36:46.680Z","contentChangedAt":"2026-09-10T12:36:46.680Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}