Skip to content

Bug: POWERTOOLS_DEV set to an empty string crashes Logger initialization #8765

Closed

Description

@zhanfan-818

Expected Behaviour

A malformed POWERTOOLS_DEV should not break construction. Per the compatibility policy in ADR 0006, I would expect a PowertoolsUserWarning and a fallback to the documented default (disabled), the same way #8728 and #8747 propose for their variables.

Current Behaviour

powertools_dev_is_set() (aws_lambda_powertools/shared/functions.py:123) calls strtobool(os.getenv(constants.POWERTOOLS_DEV_ENV, "0")). strtobool("") raises ValueError: invalid truth value '', and Logger() calls this helper during construction, so every invocation fails before the handler runs.

Observed with POWERTOOLS_DEV="":

Logger(service="svc")        ValueError: invalid truth value ''
powertools_dev_is_set()      ValueError: invalid truth value ''

Reproduction

Python 3.13.9, aws-lambda-powertools 3.39.0 from develop:

import os
os.environ["POWERTOOLS_DEV"] = ""

from aws_lambda_powertools import Logger
Logger(service="svc")   # ValueError: invalid truth value ''

Other call sites with the same shape

Verified by running them with an empty value:

  • aws_lambda_powertools/shared/functions.py:136 — POWERTOOLS_DEBUG; powertools_debug_is_set() raises ValueError, Logger() itself survives
  • aws_lambda_powertools/metrics/functions.py:158-159 — POWERTOOLS_METRICS_DISABLED; the helper raises, Metrics() itself survives
  • aws_lambda_powertools/utilities/circuit_breaker/circuit_breaker.py:96 — POWERTOOLS_CIRCUIT_BREAKER_DISABLED, same strtobool(os.getenv(...)) shape

(POWERTOOLS_IDEMPOTENCY_DISABLED and POWERTOOLS_PARAMETERS_MAX_AGE are already tracked in #8728 and #8747.)

Suggestion

Route these through one resolver that warns with PowertoolsUserWarning and falls back to the default, so a config typo degrades to the default behaviour instead of breaking every invocation.

Activity

  1. boring-cyborg commented on Nov 4, 2026

    @boring-cyborg

    Thanks for opening your first issue here! We'll come back to you as soon as we can.
    In the meantime, check out the #python channel on our Powertools for AWS Lambda Discord: Invite link

  2. powertools-for-aws-oss-automation commented on Nov 4, 2026

    @powertools-for-aws-oss-automation

    Thanks for opening your first issue here! We'll come back to you as soon as we can.
    In the meantime, check out our GitHub Discussions: Join the conversation

  3. krishbuilds01 commented on Nov 8, 2026

    @krishbuilds01
    Contributor

    Hi, I would like to work on this issue.

  4. AdepuSriCharan commented on Nov 9, 2026

    @AdepuSriCharan

    Hi @krishbuilds01, I had already worked on a local fix before seeing your comment, so I wanted to mention it to avoid duplicating work.

    My change handles empty or invalid POWERTOOLS_DEV values in powertools_dev_is_set(), falling back to False with a PowertoolsUserWarning. I've also added regression tests.

    It doesn't cover the other environment variables or the separate Metrics call site.

    If you're already working on this, no worries — I'm happy to leave it to you.

    For the maintainers, would you prefer a focused fix for POWERTOOLS_DEV or a shared solution covering the other affected variables ?

  5. zhanfan-818 commented on Nov 9, 2026

    @zhanfan-818
    Author

    Answering the scope question from @AdepuSriCharan with data: it is not just POWERTOOLS_DEV. The same one-line pattern -- os.getenv(name, default) never applying its default when the variable is present but empty -- is at seven call sites across four modules:

    File Function Variable
    shared/functions.py:124 powertools_dev_is_set POWERTOOLS_DEV
    shared/functions.py:136 powertools_debug_is_set POWERTOOLS_DEBUG
    metrics/functions.py:158 is_metrics_disabled POWERTOOLS_DEV
    metrics/functions.py:159 is_metrics_disabled POWERTOOLS_METRICS_DISABLED
    utilities/circuit_breaker/circuit_breaker.py:96 circuit_breaker POWERTOOLS_CIRCUIT_BREAKER_DISABLED
    utilities/idempotency/idempotency.py:109 _idempotent POWERTOOLS_IDEMPOTENCY_DISABLED
    utilities/idempotency/idempotency.py:219 idempotent_function POWERTOOLS_IDEMPOTENCY_DISABLED

    Reproduced on develop (111f93b): POWERTOOLS_DEV= makes Logger() raise ValueError: invalid truth value ''; same for POWERTOOLS_DEBUG via powertools_debug_is_set().

    So I opened #8782 with the shared fix -- os.getenv(name, default) -> os.getenv(name) or default, seven times, with regression tests for the two shared resolvers and for is_metrics_disabled. It stays strict for genuinely invalid values (POWERTOOLS_DEV=treu still raises), only the empty case changes to mean "not configured".

    @krishbuilds01 @AdepuSriCharan -- sorry to land in the middle of your work. A focused POWERTOOLS_DEV patch folds in trivially on top of #8782, so if either of you already has tests or a preferred shape for the warning, please push it there or say what to change and I will adjust. Not looking to duplicate effort -- whoever's patch is ready first should be the one that lands.

  6. zhanfan-818 commented on Nov 9, 2026

    @zhanfan-818
    Author

    Fair is fair -- @krishbuilds01 asked to take this first, and @AdepuSriCharan already has a patch working. I do not want to sit on someone else's work, so here is the honest state and my offer.

    #8782 is up: the shared fix across all seven call sites, plus regression tests that I verified fail on the old code and pass on the new. Nothing about it is precious.

    @AdepuSriCharan -- your shape differs from mine in one place that matters, and I picked the quieter option: you fall back to False with a PowertoolsUserWarning; mine just treats an empty value as "not configured" and says nothing. I chose silence because an empty variable is usually an accident of the deployment config, and a warning on every cold start for something the user cannot act on gets noisy fast. But that is a judgement call, not a fact -- if you think the warning belongs, say so and I will add it to #8782 with your name on the reasoning. Your regression tests are welcome there too; paste the diff here and I will fold it in.

    @krishbuilds01 -- if you have actually started, say the word and I will close #8782. I would rather lose the PR than have the two of us burn a maintainer's attention on duplicates.

    One ask: whatever happens, let us not end up with two open PRs for one issue.

  7. AdepuSriCharan commented on Nov 9, 2026

    @AdepuSriCharan

    Thanks @zhanfan-818! I'm happy to leave #8782 with you and won't open a competing PR.

    I think the warning is useful, especially for invalid values like POWERTOOLS_DEV=treu, which still raise ValueError with the current implementation. The issue mentions falling back to the default instead of breaking initialization, and #8757 follows a similar warn-and-fallback approach.

    My local fix handles both empty and invalid values in powertools_dev_is_set() by emitting a PowertoolsUserWarning and returning False.

    I've also added regression tests, and all 89 tests in the two affected test files passed locally.

    Here are the relevant tests in case they're useful:

    Regression tests
    # Add this import to both test files
    from aws_lambda_powertools.warnings import PowertoolsUserWarning
    # tests/unit/test_shared_functions.py
    
    @pytest.mark.parametrize("invalid_value", ["", " ", "maybe"])
    def test_powertools_dev_invalid_value_warns_and_falls_back(monkeypatch: pytest.MonkeyPatch, invalid_value):
        monkeypatch.setenv(constants.POWERTOOLS_DEV_ENV, invalid_value)
    
        with pytest.warns(
            PowertoolsUserWarning,
            match=f"Ignoring invalid POWERTOOLS_DEV value {invalid_value!r}",
        ):
            assert powertools_dev_is_set() is False
    # tests/functional/logger/required_dependencies/test_logger_powertools_formatter.py
    
    def test_log_json_compact_indent_when_powertools_dev_is_empty(stdout, service_name, monkeypatch):
        monkeypatch.setenv("POWERTOOLS_DEV", "")
    
        with pytest.warns(
            PowertoolsUserWarning,
            match="Ignoring invalid POWERTOOLS_DEV value ''",
        ):
            logger = Logger(service=service_name, stream=stdout)
    
        logger.info("Test message")
        assert stdout.getvalue().count(os.linesep) == 1

    These tests assume warn-and-fallback behavior, so they'll need adjustments if #8782 keeps strict validation. The warning-message assertions can also be updated to match your implementation.

    Happy to follow whatever behavior the maintainers prefer. Thanks for coordinating!

  8. krishbuilds01 commented on Nov 9, 2026

    @krishbuilds01
    Contributor

    Hi, thanks @zhanfan-818 @AdepuSriCharan . I claimed this yesterday and have the fix ready locally. Mine follows the issue text, one shared resolver across the affected call sites, and an empty or invalid value warns with PowertoolsUserWarning and falls back to the default, which is also the shape #8757 took. Happy to open it as a PR for comparison, or to step back if the maintainers prefer #8782

  9. added this to the 3.41.0 milestone on Nov 9, 2026
  10. leandrodamascena commented on Nov 9, 2026

    @leandrodamascena
    Contributor

    Thanks everyone, and sorry for the noise this turned into. Let me settle it so nobody keeps working in the dark.

    The bug is real and I am adding it to 3.41.0. It is the same family as #8728 and #8747, so the fix has to look the same.

    Behaviour: empty or invalid value warns with PowertoolsUserWarning and falls back to the default. Same shape as #8757 for POWERTOOLS_PARAMETERS_MAX_AGE. I don't want one boolean variable to fail silently on empty and another one to warn; one rule for the whole family. So POWERTOOLS_DEV=treu also warns and falls back, it does not raise.

    Scope: one resolver in shared/functions.py and use it from powertools_dev_is_set, powertools_debug_is_set, is_metrics_disabled and the circuit breaker. Leave the two call sites in idempotency.py alone: #8728 is already assigned for exactly that, and it can switch to the shared resolver once this one lands. Tests through the public API, the way @AdepuSriCharan wrote the Logger one.

    Who: @krishbuilds01 asked first, so it is yours. Please open the PR against this issue with the scope above. Review may take a few days, same as everything in 3.41.0.

    @zhanfan-818 thanks for the call-site table, it saved me time. Since you offered, please close #8782; the idempotency part of it would collide with #8728 anyway. @AdepuSriCharan your tests are welcome, @krishbuilds01 feel free to lift them.

    One ask for next time, for everybody: when someone has already claimed an issue, comment before opening a PR. It avoids exactly this.

  11. powertools-for-aws-oss-automation commented on Nov 14, 2026

    @powertools-for-aws-oss-automation

    Warning

    This issue is now closed. Please be mindful that future comments are hard for our team to see.
    If you need more assistance, please either reopen the issue, or open a new issue referencing this one.
    If you wish to keep having a conversation with other community members under this issue feel free to do so.

  12. added
    pending-releaseFix or implementation already in dev waiting to be released
    and removed
    help wantedCould use a second pair of eyes/hands
    on Nov 14, 2026
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 workingloggerpending-releaseFix or implementation already in dev waiting to be released

Type

No type

Projects

Relationships

None yet

Development

No branches or pull requests

Issue actions