{"record":{"id":"d8b2c9edaf6a41a4","repo":"apple/pkl","slug":"formatexception-key-string-ret-getclass","errorCode":null,"errorMessage":"FormatException(key, \"string\", ret.getClass())","messagePattern":"FormatException\\(key, \"string\", ret\\.getClass\\(\\)\\)","errorType":"exception","errorClass":"FormatException","httpStatus":null,"severity":"error","filePath":"pkl-core/src/main/java/org/pkl/core/util/json/Json.java","lineNumber":287,"sourceCode":"      }\n      return i;\n    }\n\n    public String getString(String key) throws JsonParseException {\n      var ret = getStringOrNull(key);\n      if (ret == null) {\n        throw new MissingFieldException(this, key);\n      }\n      return ret;\n    }\n\n    public @Nullable String getStringOrNull(String key) throws JsonParseException {\n      var ret = get(key);\n      if (ret == null) {\n        return null;\n      }\n      if (!(ret instanceof String string)) {\n        throw new FormatException(key, \"string\", ret.getClass());\n      }\n      return string;\n    }\n\n    public JsObject getObject(String key) throws JsonParseException {\n      var ret = get(key);\n      if (ret == null) {\n        throw new MissingFieldException(this, key);\n      }\n      if (!(ret instanceof JsObject jsObject)) {\n        throw new FormatException(key, \"object\", ret.getClass());\n      }\n      return jsObject;\n    }\n\n    public JsArray getArray(String key) throws JsonParseException {\n      var ret = get(key);\n      if (ret == null) {","sourceCodeStart":269,"sourceCodeEnd":305,"githubUrl":"https://github.com/apple/pkl/blob/f3efcbfc9b60d30053b0536d664948d7aa1b8673/pkl-core/src/main/java/org/pkl/core/util/json/Json.java#L269-L305","documentation":"Thrown by JsObject.getStringOrNull(String) when the key exists but the value is not a JSON string (parsed to some other Java type like Integer, JsObject, or Boolean). Unlike getString, a missing key returns null rather than throwing, so this exception only fires on present-but-wrong-typed values.","triggerScenarios":"Calling getStringOrNull(key) where the JSON value under key is a number, boolean, array, or object (e.g. {\"uri\": 42}).","commonSituations":"Upstream tool emits a URL/identifier as a number or nested object; schema drift changed a field's type; hand-edited JSON removed quotes from a string.","solutions":["Inspect the value type with get(key).getClass() to see what actually parsed","Use the matching getter for the real type (getInt, getObject, getArray)","Fix the producing side to quote the string value","Pre-check with instanceof before calling"],"exampleFix":"// before: {\"name\": 123} -> obj.getStringOrNull(\"name\") throws\n// after: {\"name\": \"123\"}","handlingStrategy":"type-guard","validationCode":"Object v = obj.get(\"name\");\nif (v != null && !(v instanceof String)) throw new IllegalStateException(\"field 'name' must be a JSON string, got \" + v.getClass().getSimpleName());","typeGuard":"boolean isStringField(JsObject o, String k) { return o.get(k) instanceof String; }","tryCatchPattern":"try { String s = obj.getStringOrNull(\"name\"); } catch (JsonParseException e) { /* handle wrong-typed value */ }","preventionTips":["Ensure string values are quoted in the JSON source","Inspect parsed types with get(key) when the producer's schema is unknown","Validate documents against a schema before field access"],"tags":["json","type-mismatch","pkl"],"backgroundTag":"type-mismatch","analyzedSha":"f3efcbfc9b60d30053b0536d664948d7aa1b8673","analyzedAt":"2026-09-08T13:10:45.570Z","contentChangedAt":"2026-09-08T13:10:45.570Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}