0

I'm encountering a panic: send on closed channel error in my Go application when handling AMQP messages using context timeouts. Here is a simplified version of the code that reproduces the issue:

func (i interactor) ScanExtension() (*AmqpMailSummaryModel, error) {
    resultChan := make(chan AmqpMailSummaryModel)
    errorChan := make(chan error)

    ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
    defer cancel()

    go func() {
        defer close(resultChan)
        defer close(errorChan)

        err := i.services.AmqpConsumer.StartConsuming(
            func(body []byte) {
                                /*
                                    body to summary model
                                */
                resultChan <- summary
            })
        if err != nil {
            errorChan <- fmt.Errorf("error starting consumer: %v", err)
        }
    }()

    /*
            messageBody process...
        */
    err = i.services.AmqpProducer.Publish(messageBody)
    if err != nil {
        return nil, fmt.Errorf("failed to publish a message: %v", err)
    }

    select {
    case result := <-resultChan:
        return &result, nil
    case err := <-errorChan:
        return nil, err
    case <-ctx.Done():
        return nil, nil
    }
}
func (c *RabbitMQConsumer) StartConsuming(handleMessage func(body []byte)) error {
    msgs, err := c.Channel.Consume(
        c.Queue,
        "",
        true,  
        false, 
        false, 
        false, 
        nil,
    )
    if err != nil {
        return err
    }

    go func() {
        for msg := range msgs {
            handleMessage(msg.Body)
        }
    }()

    return nil
}
panic: send on closed channel

goroutine 45 [running]:
tScanExtension.func1.1({0xc000782000, 0x56425a, 0x56425a})
        interactor.go:306 +0x32b
(*RabbitMQConsumer).StartConsuming.func1()
       Consumer.go:52 +0x1a8
created by (*RabbitMQConsumer).StartConsuming in goroutine 16
       Consumer.go:48 +0x15a
exit status 2

Issue: The panic: send on closed channel error occurs when handling messages and context timeouts.

Attempts: Properly closed channels, handled context timeouts, and added logging.

Question: How can I resolve the panic: send on closed channel error? Are there additional considerations for handling channels with context timeouts in Go?

Thanks for any help!

5
  • 1
    Where exactly in the send which is panicking? Commented Aug 4, 2024 at 13:34
  • @JimB This function is the business logic layer of my RESTAPI, when I send a request to this function it returns a response directly, it does not wait for the message to be consumed, after returning nil I see the message being consumed in the console and it sends a panic error, this error is caused by the defer commands in the process. Commented Aug 4, 2024 at 16:27
  • If you’re going to start a new goroutine for handleMessage, then that goroutine must also deal with cancellation. You can’t defer closing the channels from that function if you’re going to immediately dispatch the work in another goroutine, because you then will close the channels while using them. Commented Aug 4, 2024 at 16:42
  • It works on the first request and I don't get any errors, but on the other requests I just get a timeout. Commented Aug 4, 2024 at 17:00
  • Thank you both, I solved my problem by doing what you said. Commented Aug 4, 2024 at 17:33

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.