Skip to content

Bug: a missing context key satisfies negative conditions (NOT_EQUALS, NOT_IN, KEY_NOT_IN_VALUE, VALUE_NOT_IN_KEY) #8424

Description

@dreamorosi

Expected Behaviour

A condition whose key is absent from the evaluation context should not match, regardless of action. A rule written as "tier is not premium" should not fire for a request that carries no tier at all.

Current Behaviour

context.get(key) returns None for an absent key, and None is then compared as an ordinary value. None != "premium" is True, None not in [...] is True, so negative actions (NOT_EQUALS, NOT_IN, KEY_NOT_IN_VALUE, VALUE_NOT_IN_KEY) match missing keys. Rules intended to target one segment fire for anonymous or partially-populated traffic. The behaviour is not documented and no test asserts it.

Code snippet

from aws_lambda_powertools.utilities.feature_flags import FeatureFlags, RuleAction

class InMemoryStore:
    def __init__(self, d): self.d = d
    def get_configuration(self): return self.d
    @property
    def get_raw_configuration(self): return self.d

features = {
    "discount_banner": {
        "default": False,
        "rules": {
            "non premium users": {
                "when_match": True,
                "conditions": [{
                    "action": RuleAction.NOT_EQUALS.value,
                    "key": "tier",
                    "value": "premium",
                }],
            }
        },
    }
}

flags = FeatureFlags(store=InMemoryStore(features))
print(flags.evaluate(name="discount_banner", context={}, default=False))               # True (unexpected)
print(flags.evaluate(name="discount_banner", context={"tier": "free"}, default=False))  # True

Possible Solution

In _evaluate_conditions, if condition["key"] is not in context, treat the condition as not matched before calling the comparator. Time-based keys are already special-cased and would be unaffected.

This changes results for documents that, knowingly or not, rely on the current behaviour. We think it qualifies as a defect fix in the same spirit as #2051 (falsy values), where the old result was wrong rather than a designed behaviour, but we'd understand if maintainers prefer to hold it for a major. Context: the TypeScript port (aws-powertools/powertools-lambda-typescript#5614) is adopting "missing key never matches" and we'd like the two runtimes to agree.

Steps to Reproduce

Run the snippet; first print is True.

Powertools for AWS Lambda (Python) version

latest

AWS Lambda function runtime

3.13

Packaging format used

PyPi

Debugging logs

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions