Describe the bug
GBFeaturesRepository.onResponseJson (v0.9.1) parses the features endpoint response with Gson without checking whether the parse result is null, then immediately calls .get("features") on it. If the response body is empty or the literal string "null", Gson#fromJson returns null, and the subsequent .get("features") call throws an unchecked NullPointerException that propagates out of initialize() / fetchFeatures() — surfacing to the caller as a raw NPE rather than the SDK's own FeatureFetchException.
Stack trace
java.lang.NullPointerException: Attempt to invoke virtual method 'com.google.gson.JsonElement com.google.gson.JsonObject.get(java.lang.String)' on a null object reference
at growthbook.sdk.java.GBFeaturesRepository.onResponseJson(GBFeaturesRepository.java:340)
at growthbook.sdk.java.GBFeaturesRepository.onSuccess(GBFeaturesRepository.java:389)
at growthbook.sdk.java.GBFeaturesRepository.fetchFeatures(GBFeaturesRepository.java:303)
at growthbook.sdk.java.GBFeaturesRepository.initialize(GBFeaturesRepository.java:189)
To Reproduce
Call GBFeaturesRepository#initialize() (or trigger a refresh under FeatureRefreshStrategy.STALE_WHILE_REVALIDATE) against an endpoint that returns an empty body or the literal string null.
Expected behavior
The SDK should null-check the Gson parse result in onResponseJson and either surface it as a FeatureFetchException (matching the SDK's declared error-handling contract) or a GBFeaturesRepositoryException, not an unchecked NullPointerException that callers relying on the documented exception types won't catch.
Environment
growthbook-sdk-java version: 0.9.1
- Platform: Android, called from a background coroutine
- Observed in production via Firebase Crashlytics, ~first second of app session (98% of occurrences)
Workaround
We currently wrap initialize() in a broader catch (RuntimeException) on our side to avoid the crash.
Confirmed this is still present in the latest release (0.11.0). Looking at onResponseJson in the current source (now at lib/src/main/java/growthbook/sdk/java/repository/GBFeaturesRepository.java):
JsonObject jsonObject = GrowthBookJsonUtils.getInstance()
.gson.fromJson(responseJsonString, JsonObject.class); // still no null check
...
JsonElement featuresJsonElement = jsonObject.get(FeatureResponseKey.FEATURE_KEY.getKey()); // still NPEs if jsonObject is null
Gson#fromJson returns null when responseJsonString is empty or the literal string "null", and jsonObject.get(...) is still called unguarded right after. The encrypted-features branch added since 0.9.1 has the same issue (jsonObject.get(...) on the same unchecked jsonObject).
So upgrading past 0.9.1 does not resolve this — the fix still needs a null check on jsonObject before it's used, throwing FeatureFetchException (or similar) instead of letting the NPE propagate.
Describe the bug
GBFeaturesRepository.onResponseJson(v0.9.1) parses the features endpoint response with Gson without checking whether the parse result isnull, then immediately calls.get("features")on it. If the response body is empty or the literal string"null",Gson#fromJsonreturnsnull, and the subsequent.get("features")call throws an uncheckedNullPointerExceptionthat propagates out ofinitialize()/fetchFeatures()— surfacing to the caller as a raw NPE rather than the SDK's ownFeatureFetchException.Stack trace
To Reproduce
Call
GBFeaturesRepository#initialize()(or trigger a refresh underFeatureRefreshStrategy.STALE_WHILE_REVALIDATE) against an endpoint that returns an empty body or the literal stringnull.Expected behavior
The SDK should null-check the Gson parse result in
onResponseJsonand either surface it as aFeatureFetchException(matching the SDK's declared error-handling contract) or aGBFeaturesRepositoryException, not an uncheckedNullPointerExceptionthat callers relying on the documented exception types won't catch.Environment
growthbook-sdk-javaversion: 0.9.1Workaround
We currently wrap
initialize()in a broadercatch (RuntimeException)on our side to avoid the crash.Confirmed this is still present in the latest release (
0.11.0). Looking atonResponseJsonin the current source (now atlib/src/main/java/growthbook/sdk/java/repository/GBFeaturesRepository.java):Gson#fromJsonreturnsnullwhenresponseJsonStringis empty or the literal string"null", andjsonObject.get(...)is still called unguarded right after. The encrypted-features branch added since 0.9.1 has the same issue (jsonObject.get(...)on the same uncheckedjsonObject).So upgrading past 0.9.1 does not resolve this — the fix still needs a null check on
jsonObjectbefore it's used, throwingFeatureFetchException(or similar) instead of letting the NPE propagate.