Repository: getmoto/moto
Pull request #6721 (2023-08-24 17:33:59)

SQS: Fix broad catch statement for failedInvalidDelay
Hello,

I ran into an issue yesterday with SQS and sending batch messages. The actual error causing my test failures was not surfaced and it was overwritten by the `failedInvalidDelay` catch. Current local `boto3` version is `1.28.33` and the `moto` version is `4.2.0`.

Actual boto3 behavior:
```
>>> import boto3
>>> sqs = boto3.client("sqs", region_name="us-west-1")
>>> sqs.create_queue(
...     QueueName="adrian-test.fifo", Attributes=dict(FifoQueue="true")
... )
{'QueueUrl': 'https://sqs.us-west-1.amazonaws.com/123456789012/adrian-test.fifo', 'ResponseMetadata': {'RequestId': 'e7a00bb0-ec4a-5685-8fd9-56d16051e640', 'HTTPStatusCode': 200, 'HTTPHeaders': {'x-amzn-requestid': 'e7a00bb0-ec4a-5685-8fd9-56d16051e640', 'date': 'Thu, 24 Aug 2023 16:48:27 GMT', 'content-type': 'text/xml', 'content-length': '336', 'connection': 'keep-alive'}, 'RetryAttempts': 0}}
>>> entries = [
...     {
...         "Id": "id_1",
...         "MessageBody": "body_1",
...         "DelaySeconds": 0,
...         "MessageGroupId": "message_group_id_1",
...         "MessageDeduplicationId": "message_deduplication_id_1",
...     },
...     {
...         "Id": "id_2",
...         "MessageBody": "body_2",
...         "DelaySeconds": 0,
...         "MessageGroupId": "message_group_id_2",
...     },
... ]
>>> res = sqs.send_message_batch(QueueUrl="https://sqs.us-west-1.amazonaws.com/123456789012/adrian-test.fifo", Entries=entries)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/amlodzianowski/Library/Python/3.9/lib/python/site-packages/botocore/client.py", line 535, in _api_call
    return self._make_api_call(operation_name, kwargs)
  File "/Users/amlodzianowski/Library/Python/3.9/lib/python/site-packages/botocore/client.py", line 980, in _make_api_call
    raise error_class(parsed_response, operation_name)
botocore.exceptions.ClientError: An error occurred (InvalidParameterValue) when calling the SendMessageBatch operation: The queue should either have ContentBasedDeduplication enabled or MessageDeduplicationId provided explicitly
>>>
```

Current moto behavior:
```
>>> import boto3
>>> from moto import mock_sqs
>>> with mock_sqs():
...     sqs = boto3.client("sqs", region_name="us-west-1")
...     sqs.create_queue(
...         QueueName="adrian-test.fifo", Attributes=dict(FifoQueue="true")
...     )
...     entries = [
...         {
...             "Id": "id_1",
...             "MessageBody": "body_1",
...             "DelaySeconds": 0,
...             "MessageGroupId": "message_group_id_1",
...             "MessageDeduplicationId": "message_deduplication_id_1",
...         },
...         {
...             "Id": "id_2",
...             "MessageBody": "body_2",
...             "DelaySeconds": 0,
...             "MessageGroupId": "message_group_id_2",
...         },
...     ]
...     sqs.send_message_batch(QueueUrl="https://sqs.us-west-1.amazonaws.com/123456789012/adrian-test.fifo", Entries=entries)
...
{'QueueUrl': 'https://sqs.us-west-1.amazonaws.com/123456789012/adrian-test.fifo', 'ResponseMetadata': {'RequestId': 'hwP60b1yV04aC8TZOflelZ30UYd3Yla3VQBqYGAshI83KEtC7jyT', 'HTTPStatusCode': 200, 'HTTPHeaders': {'server': 'amazon.com', 'date': 'Thu, 24 Aug 2023 10:02:46 GMT', 'x-amzn-requestid': 'hwP60b1yV04aC8TZOflelZ30UYd3Yla3VQBqYGAshI83KEtC7jyT', 'x-amz-crc32': '2645304251'}, 'RetryAttempts': 0}}
{'Successful': [{'Id': 'id_1', 'MessageId': 'e04147fa-9a54-4d23-8058-2120db0aa4c9', 'MD5OfMessageBody': '074a930f749d143333deef1023ccd848'}], 'Failed': [{'Id': 'id_2', 'SenderFault': True, 'Code': 'InvalidParameterValue', 'Message': 'Value 1800 for parameter DelaySeconds is invalid. Reason: DelaySeconds must be >= 0 and <= 900.'}], 'ResponseMetadata': {'RequestId': 'qawVK75IpINGHaRjexHOtYuzvwzEbiQJxooSIY9CVkNwyVbp8ut9', 'HTTPStatusCode': 200, 'HTTPHeaders': {'server': 'amazon.com', 'date': 'Thu, 24 Aug 2023 10:02:46 GMT', 'x-amzn-requestid': 'qawVK75IpINGHaRjexHOtYuzvwzEbiQJxooSIY9CVkNwyVbp8ut9', 'x-amz-crc32': '1015589721'}, 'RetryAttempts': 0}}
>>>
```

Expected behavior mimics boto3/was added as a unit test.

Alternatively, instead of doing an if/else inside the catch block, I can raise a more specific error class here https://github.com/getmoto/moto/blob/master/moto/sqs/models.py#L869 (instead of `InvalidParameterValue`)

Please let me know if you have any questions/suggestions to get this merged in.

Best,

Adrian


Patch:
diff --git a/moto/sqs/models.py b/moto/sqs/models.py
index f9abd81b2..06c27f7fd 100644
--- a/moto/sqs/models.py
+++ b/moto/sqs/models.py
@@ -912,8 +912,11 @@ class SQSBackend(BaseBackend):
                 )
                 message.user_id = entry["Id"]  # type: ignore[attr-defined]
                 messages.append(message)
-            except InvalidParameterValue:
-                failedInvalidDelay.append(entry)
+            except InvalidParameterValue as err:
+                if "DelaySeconds is invalid" in str(err):
+                    failedInvalidDelay.append(entry)
+                else:
+                    raise err
 
         return messages, failedInvalidDelay
 


Test patch:
diff --git a/tests/test_sqs/test_sqs.py b/tests/test_sqs/test_sqs.py
index eec03ecbe..d8fa7c5b4 100644
--- a/tests/test_sqs/test_sqs.py
+++ b/tests/test_sqs/test_sqs.py
@@ -3273,3 +3273,37 @@ def test_fifo_dedupe_error_no_message_dedupe_id():
         "The queue should either have ContentBasedDeduplication enabled "
         "or MessageDeduplicationId provided explicitly"
     )
+
+
+@mock_sqs
+def test_fifo_dedupe_error_no_message_dedupe_id_batch():
+    client = boto3.client("sqs", region_name="us-east-1")
+    response = client.create_queue(
+        QueueName=f"{str(uuid4())[0:6]}.fifo", Attributes={"FifoQueue": "true"}
+    )
+    queue_url = response["QueueUrl"]
+    with pytest.raises(ClientError) as exc:
+        client.send_message_batch(
+            QueueUrl=queue_url,
+            Entries=[
+                {
+                    "Id": "id_1",
+                    "MessageBody": "body_1",
+                    "DelaySeconds": 0,
+                    "MessageGroupId": "message_group_id_1",
+                    "MessageDeduplicationId": "message_deduplication_id_1",
+                },
+                {
+                    "Id": "id_2",
+                    "MessageBody": "body_2",
+                    "DelaySeconds": 0,
+                    "MessageGroupId": "message_group_id_2",
+                },
+            ],
+        )
+
+    assert exc.value.response["Error"]["Code"] == "InvalidParameterValue"
+    assert exc.value.response["Error"]["Message"] == (
+        "The queue should either have ContentBasedDeduplication enabled "
+        "or MessageDeduplicationId provided explicitly"
+    )