Skip to content

feat!: DISABLED is a successful evaluation (still defaults)#1968

Merged
toddbaert merged 10 commits into
open-feature:mainfrom
suthar26:feat/disabled-flag-reason
Jun 1, 2026
Merged

feat!: DISABLED is a successful evaluation (still defaults)#1968
toddbaert merged 10 commits into
open-feature:mainfrom
suthar26:feat/disabled-flag-reason

Conversation

@suthar26
Copy link
Copy Markdown
Contributor

@suthar26 suthar26 commented May 25, 2026

  • Disabled flags now resolve successfully with reason=DISABLED instead of returning a FLAG_DISABLED error. See the ADR.
  • Breaking, but barely: resolved values are unchanged (SDKs still surface the caller-provided default).
  • The break is only observable for consumers that inspect reason / errorCode, call flagd directly over gRPC / OFREP, or import core/pkg/model.

Related Issues

Fixes #1966
Part of #1965

@suthar26 suthar26 requested review from a team as code owners May 25, 2026 23:24
@gemini-code-assist
Copy link
Copy Markdown
Contributor

Warning

You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again!

@netlify
Copy link
Copy Markdown

netlify Bot commented May 25, 2026

Deploy Preview for polite-licorice-3db33c canceled.

Name Link
🔨 Latest commit bcf90a6
🔍 Latest deploy log https://app.netlify.com/projects/polite-licorice-3db33c/deploys/6a1da5c94084a300085bc894

@dosubot dosubot Bot added the size:M This PR changes 30-99 lines, ignoring generated files. label May 25, 2026
@suthar26 suthar26 force-pushed the feat/disabled-flag-reason branch from 6be120a to f2d6817 Compare May 25, 2026 23:39
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR changes disabled flag evaluation from an error path to a successful evaluation with reason=DISABLED, aligning evaluator, gRPC, and OFREP behavior with the linked ADR and issue.

Changes:

  • Removes FLAG_DISABLED as a model error code and updates evaluator logic to return DISABLED without value/variant.
  • Includes disabled flags in bulk evaluation responses and adds reason-only handling for gRPC v2.
  • Updates OFREP success/error mapping and adjusts evaluator/service tests for the new behavior.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
core/pkg/evaluator/json.go Converts disabled evaluation to successful DISABLED results and includes disabled flags in bulk evaluation.
core/pkg/evaluator/json_test.go Updates evaluator expectations for disabled flags.
core/pkg/model/error.go Removes the disabled error code and readable message.
core/pkg/service/ofrep/models.go Returns disabled evaluations as OFREP success responses.
core/pkg/service/ofrep/models_test.go Removes old disabled-error status expectation.
flagd/pkg/service/flag-evaluation/flag_evaluator.go Adds disabled handling to legacy bulk responses and updates error formatting.
flagd/pkg/service/flag-evaluation/flag_evaluator_v1.go Adds disabled handling to v1 bulk responses.
flagd/pkg/service/flag-evaluation/flag_evaluator_v1_test.go Removes old disabled error-code test case.
flagd/pkg/service/flag-evaluation/flag_evaluator_test.go Removes old disabled error-code/readable-message test cases.
flagd/pkg/service/flag-evaluation/flag_evaluator_v2.go Refactors v2 response setting and adds reason-only disabled handling.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread core/pkg/evaluator/json_test.go Outdated
Comment thread core/pkg/evaluator/json_test.go
Comment thread core/pkg/evaluator/json.go
Comment thread flagd/pkg/service/flag-evaluation/flag_evaluator_v1.go Outdated
return evalErrFormatted
}

func applyResolveV2Response[T constraints](
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I generally favour the "rule of three" for duplication: with only two cases of the pattern, inline duplication wins on readability, especially with these method extractions.

@toddbaert toddbaert self-requested a review May 29, 2026 18:45
@toddbaert toddbaert changed the title feat!: return disabled reason as a successful evaluation feat!: DISABLED reason is a successful evaluation May 29, 2026
@toddbaert toddbaert changed the title feat!: DISABLED reason is a successful evaluation feat!: DISABLED is a successful evaluation (still defaults) May 29, 2026
@toddbaert toddbaert force-pushed the feat/disabled-flag-reason branch from 099468e to 102f56f Compare May 29, 2026 18:57
@toddbaert
Copy link
Copy Markdown
Member

/gemini review

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request refactors the handling of disabled flags across the evaluator, OFREP service, and flag evaluation services. Instead of returning a FLAG_DISABLED error, disabled flags now return a DisabledReason reason with omitted or zero values. Feedback on these changes includes a recommendation to populate Metadata for disabled flags in the ResolveAll response to prevent missing contextual information, and a correction to the expected JSON in BenchmarkResolveObjectValue to prevent benchmark failures.

Comment thread flagd/pkg/service/flag-evaluation/flag_evaluator_v1.go Outdated
Comment thread core/pkg/evaluator/json_test.go Outdated
suthar26 and others added 4 commits May 29, 2026 15:12
Signed-off-by: Parth Suthar <parth.suthar@dynatrace.com>
Signed-off-by: Parth Suthar <parth.suthar@dynatrace.com>
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
@toddbaert toddbaert force-pushed the feat/disabled-flag-reason branch from 102f56f to e79a26f Compare May 29, 2026 19:12
toddbaert added 3 commits May 29, 2026 15:26
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
…chmark expectation

Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
v1 (and the legacy/Old service) use proto3 scalar fields that can't
omit Value on the wire. Single-flag already emits zero values alongside
reason=DISABLED; making bulk specially-omit Value via the oneof was
inconsistent with the single-flag behavior and added complexity.

Just let bulk include disabled flags with zero values + reason=DISABLED,
matching single-flag. v2 and OFREP retain proper omission (they have
the means to omit).

Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
@toddbaert
Copy link
Copy Markdown
Member

@suthar26 v1 RPC is deprecated and basically unused, and it's not really compatible with this change I've reverted those.

Leave v1/legacy paths fully untouched; v2/core/OFREP no longer reference
this constant but it's harmless to keep around.

Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
@toddbaert
Copy link
Copy Markdown
Member

/gemini review

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request refactors the handling of disabled feature flags. Instead of treating disabled flags as errors with a FlagDisabledErrorCode, they are now treated as successful evaluations that return a specific DisabledReason with nil/empty values and no error. This change allows disabled flags to be included in bulk evaluations and properly handled in OFREP and flagd v2 services. Corresponding unit tests and benchmarks have been updated to reflect this new behavior. I have no additional feedback to provide as there are no review comments to assess.

Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
@toddbaert toddbaert requested review from a team June 1, 2026 15:02
Copy link
Copy Markdown
Member

@beeme1mr beeme1mr left a comment

Choose a reason for hiding this comment

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

Please address the relevant code quality warnings. The rest of the change looks good.

Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
@toddbaert toddbaert force-pushed the feat/disabled-flag-reason branch from a65d435 to bcf90a6 Compare June 1, 2026 15:31
@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented Jun 1, 2026

Quality Gate Failed Quality Gate failed

Failed conditions
13.3% Duplication on New Code (required ≤ 3%)

See analysis details on SonarQube Cloud

@toddbaert
Copy link
Copy Markdown
Member

toddbaert commented Jun 1, 2026

Please address the relevant code quality warnings. The rest of the change looks good.

Fixed them, just the patch duplication warning remains, which I haven't found a way to relax (and I disagree with in this case).

@toddbaert toddbaert merged commit 3c1d00b into open-feature:main Jun 1, 2026
17 of 18 checks passed
@github-actions github-actions Bot mentioned this pull request Jun 1, 2026
toddbaert added a commit that referenced this pull request Jun 1, 2026
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
toddbaert added a commit that referenced this pull request Jun 1, 2026
🤖 I have created a release *beep* *boop*
---


<details><summary>flagd: 0.16.0</summary>

##
[0.16.0](flagd/v0.15.7...flagd/v0.16.0)
(2026-06-01)


### ⚠ BREAKING CHANGES

* DISABLED is a successful evaluation (still defaults)
([#1968](#1968))
* Disabled flags now resolve successfully with `reason=DISABLED` instead
of returning a `FLAG_DISABLED` error. See the
[ADR](https://github.com/open-feature/flagd/blob/main/docs/architecture-decisions/disabled-flag-evaluation.md).
* Breaking, but barely: resolved values are unchanged (SDKs still
surface the caller-provided default).
* The break is only observable for consumers that inspect `reason` /
`errorCode`, call flagd directly over gRPC / OFREP, or import
`core/pkg/model`.

### ✨ New Features

* DISABLED is a successful evaluation (still defaults)
([#1968](#1968))
([3c1d00b](3c1d00b))
* Disabled flags now resolve successfully with `reason=DISABLED` instead
of returning a `FLAG_DISABLED` error. See the
[ADR](https://github.com/open-feature/flagd/blob/main/docs/architecture-decisions/disabled-flag-evaluation.md).
* Breaking, but barely: resolved values are unchanged (SDKs still
surface the caller-provided default).
* The break is only observable for consumers that inspect `reason` /
`errorCode`, call flagd directly over gRPC / OFREP, or import
`core/pkg/model`.
</details>

<details><summary>core: 0.16.0</summary>

##
[0.16.0](core/v0.15.8...core/v0.16.0)
(2026-06-01)


### ⚠ BREAKING CHANGES

* DISABLED is a successful evaluation (still defaults)
([#1968](#1968))
* Disabled flags now resolve successfully with `reason=DISABLED` instead
of returning a `FLAG_DISABLED` error. See the
[ADR](https://github.com/open-feature/flagd/blob/main/docs/architecture-decisions/disabled-flag-evaluation.md).
* Breaking, but barely: resolved values are unchanged (SDKs still
surface the caller-provided default).
* The break is only observable for consumers that inspect `reason` /
`errorCode`, call flagd directly over gRPC / OFREP, or import
`core/pkg/model`.

### ✨ New Features

* DISABLED is a successful evaluation (still defaults)
([#1968](#1968))
([3c1d00b](3c1d00b))
* Disabled flags now resolve successfully with `reason=DISABLED` instead
of returning a `FLAG_DISABLED` error. See the
[ADR](https://github.com/open-feature/flagd/blob/main/docs/architecture-decisions/disabled-flag-evaluation.md).
* Breaking, but barely: resolved values are unchanged (SDKs still
surface the caller-provided default).
* The break is only observable for consumers that inspect `reason` /
`errorCode`, call flagd directly over gRPC / OFREP, or import
`core/pkg/model`.
</details>

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

---------

Signed-off-by: OpenFeature Bot <109696520+openfeaturebot@users.noreply.github.com>
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Todd Baert <todd.baert@dynatrace.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:M This PR changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: disabled flag evaluation returns reason=DISABLED

5 participants