jwtk/jjwt · error · IllegalArgumentException

Invalid Gson instance - it has not been registered with the

Error message

Invalid Gson instance - it has not been registered with the necessary  type adapter.  When using the GsonBuilder, ensure this type adapter is registered by calling gsonBuilder.registerTypeHierarchyAdapter(.class, .INSTANCE) before calling gsonBuilder.create()

What it means

GsonSerializer validates at construction that the provided Gson instance can serialize ConfidentialValue; if a test-round-trip JSON contains a "value" key the Gson instance lacks the required ConfidentialValue type adapter, and IllegalArgumentException is thrown. This ensures confidential (redacted) values are serialized through the proper adapter rather than leaked as plain JSON.

Source

Thrown at extensions/gson/src/main/java/io/jsonwebtoken/gson/io/GsonSerializer.java:58

    protected final Gson gson;

    public GsonSerializer() {
        this(DEFAULT_GSON);
    }

    public GsonSerializer(Gson gson) {
        Assert.notNull(gson, "gson cannot be null.");
        this.gson = gson;

        //ensure the necessary type adapter has been registered, and if not, throw an error:
        String json = this.gson.toJson(TestConfidentialValue.INSTANCE);
        if (json.contains("value")) {
            String msg = "Invalid Gson instance - it has not been registered with the necessary " +
                    ConfidentialValue.class.getName() + " type adapter.  When using the GsonBuilder, ensure this " +
                    "type adapter is registered by calling gsonBuilder.registerTypeHierarchyAdapter(" +
                    ConfidentialValue.class.getName() + ".class, " +
                    GsonConfidentialValueSerializer.class.getName() + ".INSTANCE) before calling gsonBuilder.create()";
            throw new IllegalArgumentException(msg);
        }
    }

    @Override
    protected void doSerialize(T t, OutputStream out) {
        Writer writer = new OutputStreamWriter(out, StandardCharsets.UTF_8);
        try {
            Object o = t;
            if (o instanceof byte[]) {
                o = Encoders.BASE64.encode((byte[]) o);
            } else if (o instanceof char[]) {
                o = new String((char[]) o);
            }
            writeValue(o, writer);
        } finally {
            Objects.nullSafeClose(writer);
        }
    }

View on GitHub (pinned to fb71496164)

Solutions

  1. Register the adapter before create(): gsonBuilder.registerTypeHierarchyAdapter(ConfidentialValue.class, GsonConfidentialValueSerializer.INSTANCE)
  2. Rebuild the Gson instance with the adapter and pass it to the serializer constructor
  3. Follow the message's exact instruction including the .INSTANCE field of GsonConfidentialValueSerializer

Example fix

// before
Gson gson = new GsonBuilder().create();
Serializer<?> s = new GsonSerializer<>(gson); // IllegalArgumentException on confidential values
// after
Gson gson = new GsonBuilder()
    .registerTypeHierarchyAdapter(ConfidentialValue.class, GsonConfidentialValueSerializer.INSTANCE)
    .create();
Serializer<?> s = new GsonSerializer<>(gson);
Defensive patterns

Strategy: validation

Validate before calling

Gson gson = new GsonBuilder()
    .registerTypeHierarchyAdapter(ConfidentialValue.class, GsonConfidentialValueSerializer.INSTANCE)
    .create();
// pass this gson instance to new GsonSerializer<>(gson)

Try / catch

try {
    serializer = new GsonSerializer<>(gson);
} catch (IllegalArgumentException e) {
    throw new IllegalStateException("Rebuild Gson with the ConfidentialValue type adapter registered", e);
}

Prevention

When it happens

Trigger: Creating new GsonSerializer<>(gson) with a Gson built without gsonBuilder.registerTypeHierarchyAdapter(ConfidentialValue.class, GsonConfidentialValueSerializer.INSTANCE), then serializing claims containing ConfidentialValue.

Common situations: Setting up the Gson extension after upgrading JJWT to versions with ConfidentialCodec support; building a plain new Gson() or GsonBuilder().create() without registering the adapter.

Understand the failure class

Background: "not installed", "pip install", "required for": how missing-dependency errors surface across open-source libraries — this error's family across 34 libraries.

Related errors


AI-assisted analysis of jwtk/jjwt@fb71496164 (2026-09-09). Data as JSON: /api/errors/2ded0852aaa7e8a5. Report an issue: GitHub.