Repository: getsentry/sentry-javascript (TypeScript)

Issue:
Errors not sent when using an AWS lambda with a http proxy and the sentry lambda layer
### Is there an existing issue for this?

- [x] I have checked for existing issues https://github.com/getsentry/sentry-javascript/issues
- [x] I have reviewed the documentation https://docs.sentry.io/
- [x] I am using the latest SDK release https://github.com/getsentry/sentry-javascript/releases

### How do you use Sentry?

Sentry Saas (sentry.io)

### Which SDK are you using?

@sentry/aws-serverless

### SDK Version

10.15.0

### Framework Version

_No response_

### Link to Sentry event

_No response_

### Reproduction Example/SDK Setup

https://github.com/callumgare/sentry-lambda-http-proxy-issue/tree/http-proxy-issue (note when cloning this is not the default branch so you'll have to also checkout the "http-proxy-issue" branch)

### Steps to Reproduce

Deploy the stack in the reproduction repo above using the instructions in the README.

There should be 2 lambda urls printed in the console. Both lambdas are identical except one loads "@sentry/aws-serverless" from the Sentry's AWS lambda layer and other other from NPM. Send a request to each and for each one observe whether the error is received by sentry or not.

### Expected Result

Both lambdas should result in sentry receiving an error.

### Actual Result

The lambda which is setup to use load "@sentry/aws-serverless" from the Sentry AWS lambda layer does not successfully send the thrown error to sentry. However the other lambda, which uses "@sentry/aws-serverless" via npm installation instead of a lambda layer does send the error.

In the CloudWatch logs for the lambda layer based lambda the following is output:
```
Sentry Logger [log]: [https-proxy-agent] Creating `net.Socket`: %o { ALPNProtocols: [ 'http/1.1' ], host: '10.0.138.88', port: 3128 }
Sentry Logger [log]: [https-proxy-agent:parse-proxy-response] got proxy server response: %o %o HTTP/1.1 403 Forbidden {
server: 'squid/6.13',
'mime-version': '1.0',
date: 'Mon, 29 Sep 2025 03:23:10 GMT',
'content-type': 'text/html;charset=utf-8',
'content-length': '3490',
'x-squid-error': 'ERR_ACCESS_DENIED 0',
vary: 'Accept-Language',
'content-language': 'en',
'cache-status': 'ip-10-0-138-88.ap-southeast-2.compute.internal',
via: '1.1 ip-10-0-138-88.ap-southeast-2.compute.internal (squid/6.13)',
connection: 'close'
}
Sentry Logger [log]: [https-proxy-agent] Replaying proxy buffer for failed request
```

But in the logs for the npm based lambda this is output instead:
```
Sentry Logger [log]: [https-proxy-agent] Creating `net.Socket`: %o { ALPNProtocols: [ 'http/1.1' ], host: '10.0.138.88', port: 3128 }
Sentry Logger [log]: [https-proxy-agent:parse-proxy-response] got proxy server response: %o %o HTTP/1.1 200 Connection established 
{}

Sentry Logger [log]: [https-proxy-agent] Upgrading socket connection to TLS
```

### Additional Context

I believe the issue is connected to the fact that when "@sentry/aws-serverless" is imported from the Sentry AWS Lambda [getSDKSource()](https://github.com/getsentry/sentry-javascript/blob/0e196737dbfdd9bb14dd1920b5146f80dadb02f4/packages/core/src/utils/env.ts#L32) returns "aws-lambda-layer" due to [this](https://github.com/getsentry/sentry-javascript/blob/0e196737dbfdd9bb14dd1920b5146f80dadb02f4/packages/aws-serverless/scripts/buildLambdaLayer.ts#L208) but when "@sentry/aws-serverless" is imported from the npm installed module `getSDKSource()` will return "npm".

When `getSDKSource()` returns "aws-lambda-layer" then `useLayerExtension` will be true [here](https://github.com/getsentry/sentry-javascript/blob/0e196737dbfdd9bb14dd1920b5146f80dadb02f4/packages/aws-serverless/src/init.ts#L33). This results in the `tunnel` being set to "http://localhost:9000/envelope" [here](https://github.com/getsentry/sentry-javascript/blob/0e196737dbfdd9bb14dd1920b5146f80dadb02f4/packages/aws-serverless/src/init.ts#L41). That would be fine except because we're a http proxy sentry will send a request to the http proxy to be forwarded to "http://localhost:9000/envelope". If that proxy is on a different machine (which is likely for a http proxy since they're normally used at the edge of a network to control what traffic goes in and out) then "localhost" will refer to the machine that the proxy is running on and thus fail to reach the tunnel created by sentry.

### Possible Fixes
Ideally the request would be proxied after it passes though the tunnel rather than before but another option might be to just not turn the lambda extension on by default if a http proxy is used.

<sub>Tip: React with 👍 to help prioritize this issue. Please use comments to provide useful context, avoiding `+1` or `me too`, to help us triage it.</sub>


Discussion: <p><a href="https://linear.app/getsentry/issue/JS-999/errors-not-sent-when-using-an-aws-lambda-with-a-http-proxy-and-the">JS-999 Errors not sent when using an AWS lambda with a http proxy and the sentry lambda layer</a></p>
For a workaround for this I'm just using the version before [the lambda extension was turned on by default](https://github.com/getsentry/sentry-javascript/pull/17684):
`arn:aws:lambda:ap-southeast-2:943013980633:layer:SentryNodeServerlessSDKv10:22`

The other option (I'm assuming) would be to create your own [`instrument.js` file](https://docs.sentry.io/platforms/javascript/guides/aws-lambda/install/npm/#option-b-manual-setup) with the useLayerExtension option set to false. But in particular project I'm using this for that option is impractical for various reasons.
Hey @callumgare thanks for writing in.

Yea, either setting `useLayerExtension` or defining a `tunnel` in Sentry.init is the alternative. We can expose both as environment variables for easier configuration.

For now, downgrading layer is the only way tho.
@callumgare another workaround, if it applies to your case, would be to set `no_proxy` to `localhost,127.0.0.1` so that requests to localhosts aren't proxied. Does that help in your case?



Fix (patch):
diff --git a/CHANGELOG.md b/CHANGELOG.md
index fe9ab44858c1..358078c1fc7a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,13 @@
 
 - "You miss 100 percent of the chances you don't take. — Wayne Gretzky" — Michael Scott
 
+### Important Changes
+
+- **fix(aws-serverless): Take `http_proxy` into account when choosing
+  `useLayerExtension` default ([#17817](https://github.com/getsentry/sentry-javascript/pull/17817))**
+
+The default setting for `useLayerExtension` now considers the `http_proxy` environment variable. When `http_proxy` is set, `useLayerExtension` will be off by default. If you use a `http_proxy` but would still like to make use of the Sentry Lambda extension, exempt `localhost` in a `no_proxy` environment variable.
+
 ## 10.16.0
 
 - feat(logs): Add internal `replay_is_buffering` flag ([#17752](https://github.com/getsentry/sentry-javascript/pull/17752))
diff --git a/packages/aws-serverless/src/init.ts b/packages/aws-serverless/src/init.ts
index 6640db8ec5fa..e19cc41baf46 100644
--- a/packages/aws-serverless/src/init.ts
+++ b/packages/aws-serverless/src/init.ts
@@ -5,6 +5,44 @@ import { getDefaultIntegrationsWithoutPerformance, initWithoutDefaultIntegration
 import { DEBUG_BUILD } from './debug-build';
 import { awsIntegration } from './integration/aws';
 import { awsLambdaIntegration } from './integration/awslambda';
+
+/**
+ * Checks if proxy environment variables would interfere with the layer extension.
+ * The layer extension uses localhost:9000, so we need to check if proxy settings would prevent this.
+ */
+function shouldDisableLayerExtensionForProxy(): boolean {
+  const { http_proxy, no_proxy } = process.env;
+
+  // If no http proxy is configured, no interference (https_proxy doesn't affect HTTP requests)
+  if (!http_proxy) {
+    return false;
+  }
+
+  // Check if localhost is exempted by no_proxy
+  if (no_proxy) {
+    const exemptions = no_proxy.split(',').map(exemption => exemption.trim().toLowerCase());
+
+    // Handle common localhost exemption patterns explicitly
+    // If localhost is exempted, requests to the layer extension will not be proxied
+    const localhostExemptions = ['*', 'localhost', '127.0.0.1', '::1'];
+    if (exemptions.some(exemption => localhostExemptions.includes(exemption))) {
+      return false;
+    }
+  }
+
+  // If http_proxy is set and no localhost exemption, it would interfere
+  // The layer extension uses HTTP to localhost:9000, so only http_proxy matters
+  if (http_proxy) {
+    DEBUG_BUILD &&
+      debug.log(
+        'Disabling useLayerExtension due to http_proxy environment variable. Consider adding localhost to no_proxy to re-enable.',
+      );
+    return true;
+  }
+
+  return false;
+}
+
 /**
  * Get the default integrations for the AWSLambda SDK.
  */
@@ -28,9 +66,11 @@ export interface AwsServerlessOptions extends NodeOptions {
  */
 export function init(options: AwsServerlessOptions = {}): NodeClient | undefined {
   const sdkSource = getSDKSource();
+  const proxyWouldInterfere = shouldDisableLayerExtensionForProxy();
+
   const opts = {
     defaultIntegrations: getDefaultIntegrations(options),
-    useLayerExtension: sdkSource === 'aws-lambda-layer' && !options.tunnel,
+    useLayerExtension: sdkSource === 'aws-lambda-layer' && !options.tunnel && !proxyWouldInterfere,
     ...options,
   };
 
@@ -48,6 +88,11 @@ export function init(options: AwsServerlessOptions = {}): NodeClient | undefined
     } else {
       DEBUG_BUILD && debug.warn('The Sentry Lambda extension is only supported when using the AWS Lambda layer.');
     }
+  } else if (sdkSource === 'aws-lambda-layer' && proxyWouldInterfere) {
+    DEBUG_BUILD &&
+      debug.warn(
+        'Sentry Lambda extension disabled due to proxy environment variables (http_proxy/https_proxy). Consider adding localhost to no_proxy to re-enable.',
+      );
   }
 
   applySdkMetadata(opts, 'aws-serverless', ['aws-serverless'], sdkSource);