diff --git a/tools/flagd-core/src/main/java/dev/openfeature/contrib/tools/flagd/core/FlagdCore.java b/tools/flagd-core/src/main/java/dev/openfeature/contrib/tools/flagd/core/FlagdCore.java index 85d494ad4..db8c010b4 100644 --- a/tools/flagd-core/src/main/java/dev/openfeature/contrib/tools/flagd/core/FlagdCore.java +++ b/tools/flagd-core/src/main/java/dev/openfeature/contrib/tools/flagd/core/FlagdCore.java @@ -269,11 +269,14 @@ private ProviderEvaluation resolve(Class type, String key, EvaluationC private static ImmutableMetadata getFlagMetadata(Map currentFlagSetMetadata, FeatureFlag flag) { ImmutableMetadata.ImmutableMetadataBuilder metadataBuilder = ImmutableMetadata.builder(); - for (Map.Entry entry : currentFlagSetMetadata.entrySet()) { - addEntryToMetadataBuilder(metadataBuilder, entry.getKey(), entry.getValue()); + + if (currentFlagSetMetadata != null) { + for (Map.Entry entry : currentFlagSetMetadata.entrySet()) { + addEntryToMetadataBuilder(metadataBuilder, entry.getKey(), entry.getValue()); + } } - if (flag != null) { + if (flag != null && flag.getMetadata() != null) { for (Map.Entry entry : flag.getMetadata().entrySet()) { addEntryToMetadataBuilder(metadataBuilder, entry.getKey(), entry.getValue()); } diff --git a/tools/flagd-core/src/test/java/dev/openfeature/contrib/tools/flagd/core/FlagdCoreTest.java b/tools/flagd-core/src/test/java/dev/openfeature/contrib/tools/flagd/core/FlagdCoreTest.java index c6994838d..7feb16e39 100644 --- a/tools/flagd-core/src/test/java/dev/openfeature/contrib/tools/flagd/core/FlagdCoreTest.java +++ b/tools/flagd-core/src/test/java/dev/openfeature/contrib/tools/flagd/core/FlagdCoreTest.java @@ -1,6 +1,7 @@ package dev.openfeature.contrib.tools.flagd.core; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatNoException; import dev.openfeature.contrib.tools.flagd.api.FlagStoreException; import dev.openfeature.sdk.ImmutableContext; @@ -124,4 +125,25 @@ void setFlagsAndGetChangedKeys_detectsRemovedFlags() throws FlagStoreException { // Then: boolFlag should be in the changed keys (it was removed) assertThat(changedKeys).contains("boolFlag"); } + + @Test + void resolveBooleanValue_flagWithNullMetadata_doesNotThrowNPE() { + String configWithNullMetadata = "{" + + "\"$schema\": \"https://flagd.dev/schema/v0/flags.json\"," + + "\"flags\": {" + + " \"nullMetadataFlag\": {" + + " \"state\": \"ENABLED\"," + + " \"defaultVariant\": \"on\"," + + " \"variants\": { \"on\": true }" + + " }" + + "}" + + "}"; + + assertThatNoException().isThrownBy(() -> { + flagdCore.setFlags(configWithNullMetadata); + ProviderEvaluation result = + flagdCore.resolveBooleanValue("nullMetadataFlag", new ImmutableContext()); + assertThat(result.getFlagMetadata()).isNotNull(); + }); + } }