Lastest version 4.11.2 not working for me
Describe the bug When I upgrade to the latest version 4.11.2 it won't work at all
To reproduce Use version 4.11.2 and launch on macOS desktop target not iOS, it won't connect at all
Expected behavior It should work on macOS desktop
Logs No errors on console
SDK version 4.11.2
Language version, developer tools Flutter 3.35.3
OS/platform MacOS
Additional context macOS target, if I downgraded to 4.11.1 it will work
Hi @amrgetment , thank you for bringing this to our attention. Is your app intended for other platforms as well? If so, does 4.12.2 work on non-macOS platforms? 4.12.2 includes a change to how we handle invalid contexts. Could you provide a snippet of your configuration/initialization logic including the context building logic.
Thank you.
I tested with our example app and it works on macOS. Could you give that example app a test? There is a readme with run instructions that lets you pass your API key via command line environment.
Flutter 3.32.8 macOS 15.6.1
I made debug and this was the error, what is the invalid context I need to check
"LDClient was provided an invalid context. The context will be ignored. Existing flags will be used for evaluations until identif…"
class FeatureFlagService {
FeatureFlagService._privateConstructor();
static final FeatureFlagService instance =
FeatureFlagService._privateConstructor();
late final LDClient _launchDarklyClient;
bool _started = false;
final Completer<void> _completer = Completer<void>();
Future<void> initialize() async {
if (_completer.isCompleted) {
return Future<void>.value();
}
_started = false;
try {
_launchDarklyClient = LDClient(
LDConfig(
// for web you need client side id not mobile key
flavor.launchDarklyMobileKey,
AutoEnvAttributes.enabled,
// count of stored flag values for in on-device storage
persistence: PersistenceConfig(maxCachedContexts: 200),
logger: LDLogger(
level: UniversalPlatform.isAndroid && !isProductionFlavor()
? LDLogLevel.info
: LDLogLevel.none,
),
),
LDContextBuilder().build(),
);
} catch (e) {
critical('FeatureFlagService $e');
_completer.completeError(e);
return Future<void>.value();
}
_completer.complete();
await _completer.future;
await _listenLaunchDarklyFlags();
}
String flagsContext = 'Anonymous';
Future<void> identify({UserData? user}) async {
_started = false;
flagsContext = 'Anonymous';
final String userId = user?.id ?? '';
final String userEmail = user?.email ?? '';
final LDContext userContext = LDContextBuilder()
.kind('user', userId)
.setString('email', userEmail)
.build();
if (!_completer.isCompleted) {
await initialize();
await _completer.onCompleted(
() async {
await _launchDarklyClient.identify(
userId.isNotEmptyOrNull()
? userContext
: LDContextBuilder().build(),
);
flagsContext = 'kind:$userId, email:$userEmail';
},
onError: (dynamic err) => critical('FeatureFlagService $err'),
);
await _listenLaunchDarklyFlags();
return;
}
await _launchDarklyClient.identify(
userId.isNotEmptyOrNull() ? userContext : LDContextBuilder().build(),
);
flagsContext = 'kind:$userId, email:$userEmail';
await _listenLaunchDarklyFlags();
}
void identifyAnonymous() => identify();
LDClient? getLaunchDarklyClient() {
if (!_completer.isCompleted) {
errorLog('FeatureFlagService is not initialized');
return null;
}
_listenLaunchDarklyFlags();
return _launchDarklyClient;
}
Future<void> _listenLaunchDarklyFlags() async {
if (_started) {
return;
}
await _launchDarklyClient
.start(waitForNetworkResults: true)
.then(
(bool started) {
_started = started;
if (!started) {
critical('FeatureFlagService is not started');
return;
}
FeatureFlags().logAllFlags(flagsContext: flagsContext);
},
)
.onError((Object? error, StackTrace stackTrace) {
critical('FeatureFlagService $error');
critical('FeatureFlagService $stackTrace');
});
}
}
if it is an easy fix from my side otherwise I will use the example test you mentioned
Hey @amrgetment,
Thank you for getting back to us. There was a bug in the SDK which allowed for an invalid context to accidentally be used to initialize the SDK, which was causing some unpredictable behavior.
It sounds like you were encountering that case. All contexts must have at least 1 kind, so LDContextBuilder().build() likely just needs to be changed to LDContextBuilder().kind('user'),build() if you just want an anonymous user context when you don't have a user ID.
We will discuss if LDContextBuilder().build() should potentially just do that.
Thank you, Ryan
@kinyoklion I used version ^4.13.0 and I tried your solution LDContextBuilder().kind('user') but it didn't work for me
Hello @amrgetment did you still get the same log message?
yes same error, here is the error while I am debugging
yes same error, here is the error while I am debugging
@amrgetment - I have the same exact issue. @kinyoklion the following chnage you suggested did not work.
LDContextBuilder().kind('user').build()
I could get it to work if I did the following stub with any placeholder string. I just need to provide a value.
LDContextBuilder().kind('user','<USER>').build()
Without this stub value in the initial client instance, using the identify method does not work:
client.identify(LDContextBuilder().kind('user', user_id).build())
TLDR, at least in my case, not specifying a value for your context in your initial client instance makes subsequent identify calls meaningless. You can imagine a scenario where the context is not known until some later time.
@kinyoklion Yes I confirm, this trick works. Should I close the issue or I keep it open so it will be the default behaviour? Thanks @walsha2
LDContext getAnonymousUserContext() =>
LDContextBuilder().kind('user', 'Anonymous').build();