Repository navigation
Polling data source throws NullReferenceException on every HTTP 304 (Not Modified) response #344
Description
Summary
When using the server-side .NET SDK in polling mode, every poll that receives an HTTP 304 Not Modified response (i.e. flags haven't changed since the last poll) throws and logs a NullReferenceException. It's caught by the generic exception handler so it doesn't crash the process, but it's logged as a Warning on effectively every polling interval once the SDK has initialized and flags are stable, and it incorrectly marks the data source status as Interrupted even though nothing is actually wrong.
Root cause
In FeatureRequestor.GetAllDataAsync():
public async Task<DataSetWithHeaders> GetAllDataAsync()
{
var res = await GetAsync(_allUri);
if (res is null)
{
return null; // <-- returns a null DataSetWithHeaders reference on 304
}
...
}DataSetWithHeaders is a reference type (see IFeatureRequestor.cs), so on a 304 response GetAllDataAsync() returns a literal null, not an instance with a null DataSet property.
But in PollingDataSource.UpdateTaskAsync():
var dataAndHeaders = await _featureRequestor.GetAllDataAsync();
if (dataAndHeaders.DataSet is null) // <-- NullReferenceException here when dataAndHeaders itself is null
{
// This means it was cached, and alreadyInited was true
_dataSourceUpdates.UpdateStatus(DataSourceState.Valid, null);
}This dereferences dataAndHeaders.DataSet without first checking whether dataAndHeaders itself is null, throwing an NRE that's then caught by the generic catch (Exception ex) block further down, logged as:
Polling for feature flag updates failed: System.NullReferenceException: Object reference not set to an instance of an object.
at LaunchDarkly.Sdk.Server.Internal.DataSources.PollingDataSource.UpdateTaskAsync()
...and reported via _dataSourceUpdates.UpdateStatus(DataSourceState.Interrupted, errorInfo) — even though a 304 is a perfectly healthy "no changes" response, not an interruption.
Impact
- Every poll where flags haven't changed logs a spurious
Warning(and, if the caller has enabled the SDK's Debug logging, a matching stack trace) that looks like a real failure but isn't. DataSourceStatusis misreported asInterruptedinstead ofValidfor these no-op polls, which could affect consumers monitoring data source health viaDataSourceStatusProvider.- Flag evaluation itself is not affected, since this occurs after the flag store already has valid cached data from a prior successful poll.
Suggested fix
var dataAndHeaders = await _featureRequestor.GetAllDataAsync();
if (dataAndHeaders is null || dataAndHeaders.DataSet is null)
{
_dataSourceUpdates.UpdateStatus(DataSourceState.Valid, null);
}Repro
- SDK:
LaunchDarkly.ServerSdk8.16.0 (also confirmed present in currentmainof this repo as of 2026-09-03) - Configuration:
Components.PollingDataSource(), any poll interval, running against the real LaunchDarkly polling endpoint (https://sdk.launchdarkly.com/sdk/latest-all) - Trigger: let the client poll at least twice without any flag changes in between. The second (and every subsequent) poll that gets a 304 will throw.
Environment
- .NET 8, AWS Lambda
LaunchDarkly.ServerSdk8.16.0
Happy to submit a PR with the one-line fix above if that's helpful.
Activity
tanderson-ld commentedon Sep 3, 2026
Hi @cda210 , thank you for reporting this. We'll dig in.
tanderson-ld commentedon Sep 3, 2026
@cda210 , PR is up #345. Just waiting on teammate approval then we'll release the fix version.
fix: polling 304 responses handled appropriately (launchdarkly#345)
tanderson-ld commentedon Sep 3, 2026
@cda210 , this should be fixed in this release.
cda210 commentedon Sep 3, 2026
Thanks @tanderson-ld for the quick response. Much appreciated