apple/pkl · error · FormatException

FormatException(key, "string", ret.getClass())

Error message

FormatException(key, "string", ret.getClass())

What it means

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.

Source

Thrown at pkl-core/src/main/java/org/pkl/core/util/json/Json.java:287

      }
      return i;
    }

    public String getString(String key) throws JsonParseException {
      var ret = getStringOrNull(key);
      if (ret == null) {
        throw new MissingFieldException(this, key);
      }
      return ret;
    }

    public @Nullable String getStringOrNull(String key) throws JsonParseException {
      var ret = get(key);
      if (ret == null) {
        return null;
      }
      if (!(ret instanceof String string)) {
        throw new FormatException(key, "string", ret.getClass());
      }
      return string;
    }

    public JsObject getObject(String key) throws JsonParseException {
      var ret = get(key);
      if (ret == null) {
        throw new MissingFieldException(this, key);
      }
      if (!(ret instanceof JsObject jsObject)) {
        throw new FormatException(key, "object", ret.getClass());
      }
      return jsObject;
    }

    public JsArray getArray(String key) throws JsonParseException {
      var ret = get(key);
      if (ret == null) {

View on GitHub (pinned to f3efcbfc9b)

Solutions

  1. Inspect the value type with get(key).getClass() to see what actually parsed
  2. Use the matching getter for the real type (getInt, getObject, getArray)
  3. Fix the producing side to quote the string value
  4. Pre-check with instanceof before calling

Example fix

// before: {"name": 123} -> obj.getStringOrNull("name") throws
// after: {"name": "123"}
Defensive patterns

Strategy: type-guard

Validate before calling

Object v = obj.get("name");
if (v != null && !(v instanceof String)) throw new IllegalStateException("field 'name' must be a JSON string, got " + v.getClass().getSimpleName());

Type guard

boolean isStringField(JsObject o, String k) { return o.get(k) instanceof String; }

Try / catch

try { String s = obj.getStringOrNull("name"); } catch (JsonParseException e) { /* handle wrong-typed value */ }

Prevention

When it happens

Trigger: Calling getStringOrNull(key) where the JSON value under key is a number, boolean, array, or object (e.g. {"uri": 42}).

Common situations: 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.

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 apple/pkl@f3efcbfc9b (2026-09-08). Data as JSON: /api/errors/d8b2c9edaf6a41a4. Report an issue: GitHub.