Skip to content

fix: Check the deleted marker before decoding items from a persistent store - #266

Merged
kinyoklion merged 3 commits into
mainfrom
rlamb/sdk-2943/tombstone-raw-deleted-check
Aug 20, 2026
Merged

fix: Check the deleted marker before decoding items from a persistent store#266
kinyoklion merged 3 commits into
mainfrom
rlamb/sdk-2943/tombstone-raw-deleted-check

Conversation

@kinyoklion

@kinyoklion kinyoklion commented Aug 20, 2026

Copy link
Copy Markdown
Member

Summary

FeatureRequesterBase decoded store items into the FeatureFlag/Segment model before checking whether the item was a deleted-item tombstone. The model decoder reads key, on, salt, fallthrough, and other properties from the raw array with no defaults, under strict_types=1. A tombstone that does not carry the full schema therefore threw a TypeError during decode. TypeError is an \Error, so it escaped the catch (\Exception) guard in LDClient and surfaced as an uncaught fatal in the application.

Minimal tombstones are a realistic input: several other server SDKs write {"version":N,"deleted":true} (with no key, and none of the other properties) to shared persistent stores when a flag or segment is deleted. With such a tombstone in the store:

  • allFlagsState() fataled if the tombstone existed anywhere in the environment, even when the application never referenced the deleted flag.
  • variation()/variationDetail() fataled when evaluating the deleted flag's key.

This change checks the deleted marker on the raw JSON array in getFeature, getSegment, and getAllFeatures before invoking the model decoder. Tombstones of any shape now behave as they should: the flag reads as not found and allFlagsState() skips it. Behavior for full-schema tombstones is unchanged, including the warning log on access.

Verified against a real Redis store via the predis integration: with {"version":9,"deleted":true} stored alongside live flags, allFlagsState() and evaluation of the deleted key both fataled before this change and now succeed, with the deleted key evaluating to the default value with a FLAG_NOT_FOUND reason.

SDK-2943


Note

Overview
Stops decoding store items into FeatureFlag/Segment before noticing they are tombstones. Incomplete {"version":N,"deleted":true} records from other SDKs previously caused a TypeError (uncaught by LDClient) on variation() and allFlagsState().

getFeature, getSegment, and getAllFeatures now inspect deleted on the raw JSON and treat those items as not found (with the existing warning on single-item access). Full-schema tombstones behave the same. Tests cover live items plus full and minimal tombstones.

Reviewed by Cursor Bugbot for commit ca6a9bd. Bugbot is set up for automated code reviews on this repo. Configure here.

Comment thread src/LaunchDarkly/Impl/Model/FeatureFlag.php Outdated

@jsonbailey jsonbailey left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor nit on the comments.

@kinyoklion
kinyoklion marked this pull request as ready for review August 20, 2026 18:21
@kinyoklion
kinyoklion requested a review from a team as a code owner August 20, 2026 18:21
@kinyoklion
kinyoklion merged commit a40614b into main Aug 20, 2026
18 checks passed
@kinyoklion
kinyoklion deleted the rlamb/sdk-2943/tombstone-raw-deleted-check branch August 20, 2026 22:14
kinyoklion pushed a commit that referenced this pull request Aug 24, 2026
🤖 I have created a release *beep* *boop*
---


##
[6.8.3](6.8.2...6.8.3)
(2026-08-20)


### Bug Fixes

* Check the deleted marker before decoding items from a persistent store
([#266](#266))
([a40614b](a40614b))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Overview**
> Release Please version bump to **6.8.3**.
> 
> Updates `LDClient::VERSION`, the release-please manifest, and the
phpDocumentor title. Changelog notes the bugfix: check the deleted
marker before decoding items from a persistent store (#266).
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
ac5b714. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants