aws / aws-sam-cli

CLI tool to build, test, debug, and deploy Serverless applications using AWS SAM
https://aws.amazon.com/serverless/sam/
Apache License 2.0
6.48k stars 1.16k forks source link

`'str' object has no attribute 'decode'` when `PortAlreadyInUse` error is raised. #7244

Open DiscreteTom opened 1 month ago

DiscreteTom commented 1 month ago

https://github.com/aws/aws-sam-cli/blob/5570367805bc94e43755e31a493b7cb93677dde3/samcli/local/docker/container.py#L392

Remove .decode() to resolve this issue.

lucashuy commented 1 month ago

Thanks for reporting this, just so that we can reproduce this, can you fill out the bug template? We just want to confirm before removing the decode as this is the first we are seeing about this, and could be a breaking change if the decode was removed.

<!-- Make sure we don't have an existing Issue that reports the bug you are seeing (both open and closed). 
If you do find an existing Issue, re-open or add a comment to that Issue instead of creating a new one. -->

### Description:
<!-- Briefly describe the bug you are facing.-->

### Steps to reproduce:
<!-- Provide detailed steps to replicate the bug, including steps from third party tools (CDK, etc.) -->

### Observed result:
<!-- Please provide command output with `--debug` flag set. -->

### Expected result:
<!-- Describe what you expected. -->

### Additional environment details (Ex: Windows, Mac, Amazon Linux etc)

<!-- Either provide the following info (for AWS SAM CLI v1.68.0 or before) or paste the output of `sam --info` (AWS SAM CLI v1.69.0 or after). -->

1. OS:
2. `sam --version`:
3. AWS region:

Paste the output of sam --info here


`Add --debug flag to command you are running`
DiscreteTom commented 1 month ago

Description:

sam local start-api got 'str' object has no attribute 'decode' when PortAlreadyInUse error is raised.

Steps to reproduce:

This issue occurs when requesting the local mock api (e.g. curl http://localhost:3000/v1/pets) after sam local start-api. Still trying to find a stable way to reproduce this issue.

Theoretically PortAlreadyInUse shouldn't happen because the following function

https://github.com/aws/aws-sam-cli/blob/2548a62b27810c5a362ddd8c0e13e2e430b43dc5/samcli/local/docker/utils.py#L54

but sometimes it indeed happened. And when it happened, the ex.explanation is a string and the above error occur.

I fixed this in my local container.py script and it works nicely.

Observed result:

Since I haven't find a stable way to reproduce this, here is the only remained info from a sceenshot I took earlier.

    container.start(input_data=input_data)
File 'C:\ProgramFiles\Amazon\AWSSAMCLI\runtime\Lib\site-packages\samcli\local\docker\container.py",line 378, in
    raise PortAlreadyInUse(ex.explanation.decode()) from ex
                           ^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'str' object has no attribute 'decode'
2024-07-12 14:27:57 127.0.0.1 - - [12/Jul/2024 14:27:57] "GET /v1/pets HTTP/1.1" 502 -
2024-07-12 14:27:57 127.0.0.1 - - [12/Jul/2024 14:27:57] "GET /favicon.ico HTTP/1.1" 403 -

This should be a PortAlreadyInUse error and users could see which port is occupied. But now that error is interrupted by the AttributeError.

Expected result:

The actual error should be the PortAlreadyInUse. After I fixed this issue, the output is like:

2024-07-12 17:29:50,791 | arn:aws:lambda:ap-southeast-1:753240598075:layer:LambdaAdapterLayerX86:22 is already cached. Skipping download
2024-07-12 17:29:50,806 | Checking free port on 127.0.0.1:8725
2024-07-12 17:29:50,813 | Using local image: samcli/lambda-java:17-x86_64-d97bac8a5baa36a91f3a926a4.

2024-07-12 17:29:50,814 | Mounting E:\code\xxx-springboot-web-aws-adapter\.aws-sam\build\PetstoreFunction as /var/task:ro,delegated, inside runtime container
2024-07-12 17:29:50,949 | [Container state] OOMKilled False
2024-07-12 17:29:50,987 | Cleaning all decompressed code dirs
2024-07-12 17:29:50,991 | Exception on /v1/pets [GET]
Traceback (most recent call last):
  File "C:\Program Files\Amazon\AWSSAMCLI\runtime\Lib\site-packages\docker\api\client.py", line 265, in _raise_for_status
    response.raise_for_status()
  File "C:\Program Files\Amazon\AWSSAMCLI\runtime\Lib\site-packages\requests\models.py", line 1021, in raise_for_status
    raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 500 Server Error: Internal Server Error for url: http+docker://localnpipe/v1.35/containers/72819bb0596b8c412be705008ec84816a1a4361382fbfc90ee0750a7a0016781/start

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "C:\Program Files\Amazon\AWSSAMCLI\runtime\Lib\site-packages\flask\app.py", line 1463, in wsgi_app
    response = self.full_dispatch_request()
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Amazon\AWSSAMCLI\runtime\Lib\site-packages\flask\app.py", line 872, in full_dispatch_request
    rv = self.handle_user_exception(e)
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Amazon\AWSSAMCLI\runtime\Lib\site-packages\flask\app.py", line 870, in full_dispatch_request
    rv = self.dispatch_request()
         ^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Amazon\AWSSAMCLI\runtime\Lib\site-packages\flask\app.py", line 855, in dispatch_request
    return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)  # type: ignore[no-any-return]
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Amazon\AWSSAMCLI\runtime\Lib\site-packages\samcli\local\apigw\local_apigw_service.py", line 724, in _request_handler
    lambda_response = self._invoke_lambda_function(route.function_name, route_lambda_event)
                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Amazon\AWSSAMCLI\runtime\Lib\site-packages\samcli\local\apigw\local_apigw_service.py", line 617, in _invoke_lambda_function
    self.lambda_runner.invoke(lambda_function_name, event_str, stdout=stdout_writer, stderr=self.stderr)
  File "C:\Program Files\Amazon\AWSSAMCLI\runtime\Lib\site-packages\samcli\commands\local\lib\local_lambda.py", line 149, in invoke
    self.local_runtime.invoke(
  File "C:\Program Files\Amazon\AWSSAMCLI\runtime\Lib\site-packages\samcli\lib\telemetry\metric.py", line 325, in wrapped_func
    return_value = func(*args, **kwargs)
                   ^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Amazon\AWSSAMCLI\runtime\Lib\site-packages\samcli\local\lambdafn\runtime.py", line 203, in invoke
    container = self.run(container, function_config, debug_context)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Amazon\AWSSAMCLI\runtime\Lib\site-packages\samcli\local\lambdafn\runtime.py", line 153, in run
    self._container_manager.run(container)
  File "C:\Program Files\Amazon\AWSSAMCLI\runtime\Lib\site-packages\samcli\local\docker\manager.py", line 118, in run
    container.start(input_data=input_data)
  File "C:\Program Files\Amazon\AWSSAMCLI\runtime\Lib\site-packages\samcli\local\docker\container.py", line 379, in start
    raise ex
  File "C:\Program Files\Amazon\AWSSAMCLI\runtime\Lib\site-packages\samcli\local\docker\container.py", line 375, in start
    real_container.start()
  File "C:\Program Files\Amazon\AWSSAMCLI\runtime\Lib\site-packages\docker\models\containers.py", line 417, in start
    return self.client.api.start(self.id, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Amazon\AWSSAMCLI\runtime\Lib\site-packages\docker\utils\decorators.py", line 19, in wrapped
    return f(self, resource_id, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Amazon\AWSSAMCLI\runtime\Lib\site-packages\docker\api\container.py", line 1135, in start
    self._raise_for_status(res)
  File "C:\Program Files\Amazon\AWSSAMCLI\runtime\Lib\site-packages\docker\api\client.py", line 267, in _raise_for_status
    raise create_api_error_from_http_exception(e) from e
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Amazon\AWSSAMCLI\runtime\Lib\site-packages\docker\errors.py", line 39, in create_api_error_from_http_exception
    raise cls(e, response=response, explanation=explanation) from e
docker.errors.APIError: 500 Server Error for http+docker://localnpipe/v1.35/containers/72819bb0596b8c412be705008ec84816a1a4361382fbfc90ee0750a7a0016781/start: Internal Server Error ("Ports are not available: exposing port TCP      
127.0.0.1:8725 -> 0.0.0.0:0: listen tcp 127.0.0.1:8725: bind: Only one usage of each socket address (protocol/network address/port) is normally permitted.")
2024-07-12 17:29:51,023 | Lambda execution failed (<InternalServerError '500: Internal Server Error'>,)

But why the PortAlreadyInUse was throwed? That's another topic... still investigating...

Additional environment details (Ex: Windows, Mac, Amazon Linux etc)

  1. OS: Windows
  2. sam --version: 1.113.0
  3. AWS region: test locally
{
  "version": "1.113.0",
  "system": {
    "python": "3.11.8",
    "os": "Windows-10-10.0.19044-SP0"
  },
  "additional_dependencies": {
    "docker_engine": "Not available",
    "aws_cdk": "Not available",
    "terraform": "Not available"
  },
  "available_beta_feature_env_vars": [
    "SAM_CLI_BETA_FEATURES",
    "SAM_CLI_BETA_BUILD_PERFORMANCE",
    "SAM_CLI_BETA_TERRAFORM_SUPPORT",
    "SAM_CLI_BETA_RUST_CARGO_LAMBDA"
  ]
}

Add --debug flag to command you are running