Fix RemoteConfig.all returning defaults instead of fetched values on Apple - #848
Open
anggrayudi wants to merge 1 commit into
Open
Fix RemoteConfig.all returning defaults instead of fetched values on Apple#848anggrayudi wants to merge 1 commit into
anggrayudi wants to merge 1 commit into
Conversation
`all` read every key once per source and merged the results with `toMap()`.
Because `Default` was listed last and `toMap()` keeps the last pair for a
duplicate key, a key present in both the remote and default sources resolved
to the default, shadowing the fetched remote value. Callers who had called
setDefaults() therefore saw stale defaults from `all` even after a successful
fetchAndActivate(), while dropping setDefaults() made the remote values
appear.
Collect the key set across sources instead, then resolve each key through
configValueForKey(key) so Firebase applies its own precedence
(remote > default > static). This matches the JS target, which already does
getAllKeys().associateWith { getValue(it) }, and Android, which delegates to
the native `all`.
getKeysByPrefix() is built on `all` and was affected the same way.
Fixes GitLiveApp#427
This was referenced Aug 5, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #427.
Problem
On Apple targets,
FirebaseRemoteConfig.allread every key once per source and merged the results:Two things combine badly here:
configValueForKey(key, source), so it bypasses Remote Config's own precedence; andtoMap()keeps the last pair for a duplicate key, andDefaultis listed last.So for any key present in both the remote and default sources,
allreturns the default, shadowing the value that was just fetched.That matches the report exactly: with
setDefaults(...)the reporter saw stale defaults out ofalleven though the logs showed a successful fetch and activate, and removingsetDefaults(...)made the remote values appear — because with no defaults registered there is no colliding key to overwrite them.The documented precedence is remote > default > static, so this is backwards.
Apple was the only target with the problem:
getAllKeys().associateWith { getValue(it) }all, which applies precedence itselfFix
Collect the key set across the three sources, then resolve each key through
configValueForKey(key)— the single-argument overload the class already uses ingetValue()— so Firebase applies its own precedence. This is the same shape as the JS implementation.getKeysByPrefix()is implemented on top ofall, so it was affected the same way and is fixed by the same change.On testing
I could not run the build or the tests locally — Gradle dependency resolution stalls in my environment and I never got a green or red run, the same as I noted on #847. Please treat CI as the real check.
More importantly, this is not something the existing suite could have caught, and I want to be explicit about why rather than imply otherwise.
testGetAllonly callssetDefaults(...)and never fetches, so every key comes from the default source alone — there is no collision, and the test passes identically before and after this change. A genuine regression test needs a key that exists in both the remote and default sources, which means real remote values; that is exactly whytestFetchandtestFetchAndActivateare@Ignored, since Remote Config isn't covered by the Firebase emulator.So rather than add a test that cannot fail, I extended the existing
@IgnoredtestFetchAndActivateto register a default under the same key as the remote value and assert thatallagrees withgetValue. It won't run in CI, but it encodes the regression and makes it verifiable by anyone running that test manually against a project with the console value set.Happy to take a different approach if you'd prefer the precedence pinned by an explicitly ordered merge instead of delegating to
configValueForKey(key).