Skip to content

Allow stack traces in HTTP responses only if INCLUDE_STACK_TRACES_IN_HTTP_RESPONSE is enabled #12938

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 10 commits into
base: main
Choose a base branch
from

Conversation

sannya-singal
Copy link
Contributor

@sannya-singal sannya-singal commented Jul 31, 2025

Motivation

As a part of the initiative for improving Localstack error messages, this PR aims to conditionally remove stack traces from HTTP responses. A new environment variable INCLUDE_STACK_TRACES_IN_HTTP_RESPONSE is introduced, which when enabled, allows stack traces to be included in the HTTP response.
This is expected to be always enabled during test runs, where it improves LocalStack developers devX, unless its explicitly disabled. This flag is for internal use only. The stack traces wouldn't appear in the HTTP responses for users unlike before when DEBUG is enabled.

Current Behaviour:

sannyasingal@Sannyas-MacBook-Pro ~ % awslocal organizations describe-organization

An error occurred (InternalError) when calling the DescribeOrganization operation (reached max retries: 4): exception while calling organizations.DescribeOrganization: Traceback (most recent call last):
  File "/opt/code/localstack/.venv/lib/python3.11/site-packages/rolo/gateway/chain.py", line 166, in handle
    handler(self, self.context, response)
  File "/opt/code/localstack/.venv/lib/python3.11/site-packages/localstack/aws/handlers/service.py", line 112, in __call__
    handler(chain, context, response)
  File "/opt/code/localstack/.venv/lib/python3.11/site-packages/localstack/aws/handlers/service.py", line 82, in __call__
    skeleton_response = self.skeleton.invoke(context)
                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/code/localstack/.venv/lib/python3.11/site-packages/localstack/aws/skeleton.py", line 154, in invoke
    return self.dispatch_request(serializer, context, instance)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/code/localstack/.venv/lib/python3.11/site-packages/localstack/aws/skeleton.py", line 168, in dispatch_request
    result = handler(context, instance) or {}
             ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/code/localstack/.venv/lib/python3.11/site-packages/localstack/aws/forwarder.py", line 133, in _call
    return handler(context, req)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/opt/code/localstack/.venv/lib/python3.11/site-packages/localstack/aws/skeleton.py", line 118, in __call__
    return self.fn(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/code/localstack/.venv/lib/python3.11/site-packages/localstack/pro/core/services/organizations/provider.py", line 304, in describe_organization
    a = org[0]
        ~~~^^^
TypeError: 'NoneType' object is not subscriptable

Expected Behaviour:

sannyasingal@Sannyas-MacBook-Pro ~ % awslocal organizations describe-organization

An error occurred (InternalError) when calling the DescribeOrganization operation (reached max retries: 4): exception while calling organizations.DescribeOrganization: 'NoneType' object is not subscriptable

Changes

This PR excludes stack traces from HTTP responses when DEBUG=1 mode is enabled (for DEBUG=0 we already do not log stack trace in the response) and rather allow stack traces when INCLUDE_STACK_TRACES_IN_HTTP_RESPONSE is enabled.
Related PR in pro https://github.com/localstack/localstack-pro/pull/5003

Testing

The responses to:

  • local test runs by enabling and disabling INCLUDE_STACK_TRACES_IN_HTTP_RESPONSE have been tested locally by deliberately introducing an error by assigning a = request["KeyId"][100] in describe_key handler and run awslocal kms describe-key --key-id=411cff4c-e1d0-49cc-9ec7-73ac91049d86 command ensuring expected stack trace behaviour for both cases.
  • CI run with a failing operation https://github.com/localstack/localstack/actions/runs/16820674492/job/47646766927?pr=12938 ensuring expected stack trace behaviour when enabled.

TODO

  • test CI run with a failing operation

@sannya-singal sannya-singal added this to the 4.8 milestone Jul 31, 2025
@sannya-singal sannya-singal self-assigned this Jul 31, 2025
@sannya-singal sannya-singal added the semver: minor Non-breaking changes which can be included in minor releases, but not in patch releases label Jul 31, 2025
@localstack-bot
Copy link
Contributor

Currently, only patch changes are allowed on main. Your PR labels (semver: minor) indicate that it cannot be merged into the main at this time.

1 similar comment
@localstack-bot
Copy link
Contributor

Currently, only patch changes are allowed on main. Your PR labels (semver: minor) indicate that it cannot be merged into the main at this time.

Copy link

github-actions bot commented Jul 31, 2025

Test Results - Preflight, Unit

22 063 tests  ±0   20 329 ✅ ±0   6m 21s ⏱️ -1s
     1 suites ±0    1 734 💤 ±0 
     1 files   ±0        0 ❌ ±0 

Results for commit df061e4. ± Comparison against base commit 2d08a27.

♻️ This comment has been updated with latest results.

Copy link

github-actions bot commented Jul 31, 2025

Test Results (amd64) - Acceptance

7 tests  ±0   5 ✅ ±0   3m 13s ⏱️ +8s
1 suites ±0   2 💤 ±0 
1 files   ±0   0 ❌ ±0 

Results for commit df061e4. ± Comparison against base commit 2d08a27.

♻️ This comment has been updated with latest results.

Copy link

github-actions bot commented Jul 31, 2025

Test Results (amd64) - Integration, Bootstrap

    5 files      5 suites   2h 20m 29s ⏱️
4 982 tests 4 393 ✅ 589 💤 0 ❌
4 988 runs  4 393 ✅ 595 💤 0 ❌

Results for commit df061e4.

♻️ This comment has been updated with latest results.

@coveralls
Copy link

Coverage Status

coverage: 83.175% (+31.8%) from 51.395%
when pulling 08fc74c on rm-stack-traces-http-resp
into 476e7f3 on main.

Copy link

github-actions bot commented Jul 31, 2025

LocalStack Community integration with Pro

    2 files  ±0      2 suites  ±0   1h 42m 29s ⏱️ - 1m 53s
4 623 tests +2  4 186 ✅ ±0  437 💤 +2  0 ❌ ±0 
4 625 runs  +2  4 186 ✅ ±0  439 💤 +2  0 ❌ ±0 

Results for commit df061e4. ± Comparison against base commit 2d08a27.

This pull request removes 1 and adds 3 tests. Note that renamed tests count towards both.
tests.aws.services.cloudformation.resources.test_cdk.TestCdkInit ‑ test_cdk_bootstrap_redeploy
tests.aws.services.cloudformation.resources.test_cdk.TestCdkInit ‑ test_cdk_bootstrap[28]
tests.aws.services.cloudformation.resources.test_cdk.TestCdkInit ‑ test_cdk_bootstrap_redeploy[v20]
tests.aws.services.cloudformation.resources.test_cdk.TestCdkInit ‑ test_cdk_bootstrap_redeploy[v28]

♻️ This comment has been updated with latest results.

@sannya-singal sannya-singal requested a review from k-a-il July 31, 2025 08:54
@sannya-singal sannya-singal marked this pull request as ready for review July 31, 2025 08:54
@sannya-singal sannya-singal requested a review from thrau as a code owner July 31, 2025 08:54
@k-a-il k-a-il requested a review from bentsku July 31, 2025 08:56
Copy link
Member

@thrau thrau left a comment

Choose a reason for hiding this comment

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

general question: if we remove this, how does the devx look like for localstack developers? the stacktrace is added when DEBUG=1 is set so the stack traces appear in test failures directly, which has helped (at least me) in the past to find issues very quickly.

@bentsku
Copy link
Contributor

bentsku commented Jul 31, 2025

general question: if we remove this, how does the devx look like for localstack developers? the stacktrace is added when DEBUG=1 is set so the stack traces appear in test failures directly, which has helped (at least me) in the past to find issues very quickly.

That's a good point: it returns the error directly in the client call, which allows the test annotation to show the error directly and not have to go through the logs of the running LocalStack instance.

I think there's a fine line with the customer running with DEBUG=1 and what we show. But returning stack traces in error is IMHO a behavior change that is a bit more intrusing that just the debug level.
Maybe this should be a different flag, and not only rely on the logging level, but with another environment variable that would be set to true while running tests? Something that we could directly automatically enable via a fixture? That way, we'd keep the internal DevX while still prevent customers to see those stack traces.

@thrau
Copy link
Member

thrau commented Aug 1, 2025

that's fair. so perhaps instead of removing the behavior (returning stack traces) all together, we could tie it to our tests being run. for example os.environ[constants.ENV_INTERNAL_TEST_RUN], will be set for integration tests and we could use that instead of config.DEBUG

@sannya-singal sannya-singal marked this pull request as draft August 1, 2025 10:23
Copy link

github-actions bot commented Aug 6, 2025

S3 Image Test Results (AMD64 / ARM64)

    2 files    2 suites   8m 52s ⏱️
  515 tests 465 ✅  50 💤 0 ❌
1 030 runs  930 ✅ 100 💤 0 ❌

Results for commit df061e4.

♻️ This comment has been updated with latest results.

@sannya-singal sannya-singal force-pushed the rm-stack-traces-http-resp branch from f103562 to 5c4c022 Compare August 6, 2025 07:31
@sannya-singal sannya-singal force-pushed the rm-stack-traces-http-resp branch from 5c4c022 to 0fde5fd Compare August 7, 2025 06:55
@sannya-singal sannya-singal changed the title Remove stack traces from HTTP responses Allow stack traces in HTTP responses only if INCLUDE_STACK_TRACES_IN_HTTP_RESPONSE is enabled Aug 7, 2025
@sannya-singal sannya-singal marked this pull request as ready for review August 8, 2025 07:39
Copy link
Contributor

@bentsku bentsku left a comment

Choose a reason for hiding this comment

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

I have a question regarding adding the flag to our config.py file instead of directly manipulating environment variables, not sure if I miss some context. Maybe it is because it is internal only?

For the other "test only" variables like LOCALSTACK_INTERNAL_TEST_RUN and LOCALSTACK_INTERNAL_TEST_COLLECT_METRIC, they don't change LocalStack behavior, only the tests behavior, which is maybe why they are not added to config.py.

Here we're directly directing LocalStack behavior, so I think we might be better if it is a proper config flag, what do you think?

As a side-note, it could also allow us to keep the current behavior until the next release (where we would only flip the flag) to not modify behavior suddenly, but to be honest I'm not sure it is worth it, I don't see what it would bring to our users, so I think we can change it in latest 😄

Comment on lines 188 to 191
if (
os.environ.get(constants.INCLUDE_STACK_TRACES_IN_HTTP_RESPONSE)
in constants.TRUE_STRINGS
):
Copy link
Contributor

Choose a reason for hiding this comment

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

question: was there a specify reason that would prevent us from adding INCLUDE_STACK_TRACES_IN_HTTP_RESPONSE to config like other configuration variables? It would more easily discoverable, and we could still patch it in the fixture with monkeypatch.setattr(config, "INCLUDE_STACK_TRACES_IN_HTTP_RESPONSE", True)

But maybe I am missing something?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for raising this 🙌 There was no strong reason not to add it to config.py, the flag was introduced mainly for internal use so took this approach. But I agree that making it a proper config flag would improve discoverability also since this flag affects the LocalStack behaviour. I will go ahead and move it to config.py with a default of 0, and patch it to 1 in the fixture and also make relevant changes in pro 👍

Copy link
Contributor

@k-a-il k-a-il left a comment

Choose a reason for hiding this comment

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

LGTM 👍

Comment on lines 94 to 101
@pytest.fixture(autouse=True)
def enable_stack_trace_for_tests(monkeypatch):
"""
Ensure stack traces are enabled in HTTP responses during test sessions.
This is useful for debugging purposes.
"""
monkeypatch.setenv(INCLUDE_STACK_TRACES_IN_HTTP_RESPONSE, "1")
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: we could create a session scope fixture too with MonkeyPatch directly: pytest-dev/pytest#1872 (comment)

See here where we do it for a class fixture:

@pytest.fixture(scope="class")
def patch_opensearch_strategy(self):
"""patching the endpoint strategy for opensearch to path, to make the endpoint resolution in the lambda easier"""
from _pytest.monkeypatch import MonkeyPatch
from localstack import config
mpatch = MonkeyPatch()
mpatch.setattr(config, "OPENSEARCH_ENDPOINT_STRATEGY", "path")
yield mpatch
mpatch.undo()

@sannya-singal sannya-singal requested a review from bentsku August 8, 2025 10:46
Copy link
Contributor

@bentsku bentsku left a comment

Choose a reason for hiding this comment

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

LGTM, thanks for addressing the comments 🚀

@@ -71,6 +71,8 @@ def pytest_runtestloop(session: Session):

# configure
os.environ[ENV_INTERNAL_TEST_RUN] = "1"
localstack_config.INCLUDE_STACK_TRACES_IN_HTTP_RESPONSE = True
Copy link
Contributor

Choose a reason for hiding this comment

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

question: do we need this if we have the fixture? I guess it cannot hurt, so I'm fine leaving it like that 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
semver: minor Non-breaking changes which can be included in minor releases, but not in patch releases
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants