32

I switched to a FIFO queue and I got this error message when I tried to delete a message from the queue

Value {VALUE} for parameter ReceiptHandle is invalid. Reason: The receipt handle has expired.

It appears that the error happens because I tried to delete the message after visibility timeout has expired. I changed the default visibility timeout 0 to the maximum, 12 hours, this solved partially the issue. Sometimes it could happens that a message still in my queue for longer than 12 hours before I could perform it and than delete it, so I will get the error again. Is there any solution to increase the visibility timeout for more than 12 hours or to bypass this error by another way?

doej
  • 449
  • 1
  • 5
  • 5

5 Answers5

39

You can do it in AWS Console, but the trick is, you have to do it while the Polling progress is still active.
For example, when you poll for 10 seconds, and 10 messages, you need to delete the message within 10 seconds or before 10th messages arrived, whichever comes first, after the polling stopped, your window of deletion closed.

You get error when polling stopped You get error when polling stopped

Adjust polling duration, and message count Adjust polling duration, and message count

While polling, select the message and delete
while polling in progress, select and delete

Message deleted successfully. Message deleted successfully.

Weicheng
  • 717
  • 7
  • 10
  • 1
    This does not work for me. I still get the error message even if I do the delete within the polling window. – J T Aug 21 '23 at 20:26
  • Same in my case, messages are not getting deleted, I have set it to 1 hour. Message is getting processed in few mins. – Tmh Aug 22 '23 at 12:04
23

TLDR: You want to look into the ChangeMessageVisibility API.

Details

The reason for visibility timeout is to make sure the process handling the message hasn't unexpectedly died, and allow the message to be processed by a different worker.

If your process needs to take longer than the configured visibility timeout, it essentially needs to send some signal to SQS that says "I'm still alive and working on this message". That's what ChangeMessageVisibility is for.

If you have wide variability in the time required to consume and process a message, I suggest setting a small-ish default visibility timeout and having your workers emit a "heartbeat" (using ChangeMessageVisibility) to indicate they're still alive and working on the message. That way you can still recover relatively quickly when a worker legitimately fails.

Note there is also ChangeMessageVisibilityBatch for doing this on batches of messages.

Krease
  • 15,805
  • 8
  • 54
  • 86
15

Try increasing the value of VisibilityTimeout parameter in sqs.receive_message() for the message you wish to delete using ReceiptHandle

  • 2
    Thanks man, that was it. I thought VisibilityTimeout was only set on the Queue itself but it turned out the VisibilityTimeout on the boto3 call overrides that and makes the message undeletable. Changing it as you suggested solved the problem – George Smith Oct 17 '19 at 18:54
3

change VisibilityTimeout:0 to VisibilityTimeout:60 it's working

const params = {
        AttributeNames:[
            "SentTimestamp"
        ],
        MaxNumberOfMessages:10,
        MessageAttributeNames:[
            "All"
        ],
        QueueUrl:queueURL,
        VisibilityTimeout:60,
        WaitTimeSeconds:0,
    };
    sqs.receiveMessage(params,function (err,data) {
        console.log(data);
        if (err) {
            console.log("Receive Error", err);
        }else if (data.Messages) {
            let deleteParams = {
              QueueUrl: queueURL,
              ReceiptHandle: data.Messages[0].ReceiptHandle
            };
            sqs.deleteMessage(deleteParams, function(err, data) {
                  if (err) {
                    console.log("Delete Error", err);
                  } else {
                    console.log("Message Deleted", data);
                  }
            });
         }
    });
Sajeenthiran
  • 417
  • 5
  • 11
3

setting VisibilityTimeout greater than 0 will work