bot icon indicating copy to clipboard operation
bot copied to clipboard

encounter same error every few hours

Open g-mero opened this issue 2 months ago • 3 comments

The getMe method runs about every two minutes.

error do request for method getMe, Post "https://api.telegram.org/bot***/getMe": http2: Transport: cannot retry err [http2: Transport received Server's graceful shutdown GOAWAY] after Request.Body was written; define Request.GetBody to avoid this error

Image

g-mero avatar Oct 30 '25 01:10 g-mero

Hello! Can you provide more information?

  1. What is the output in defaultErrorsHandler() -> [TGBOT] [ERROR] ...?
  2. And what does the code from msg_handle_bet.go look like?

steindvart avatar Oct 30 '25 05:10 steindvart

@Steindvart

  1. I couldn’t find any output in defaultErrorsHandler(). Here’s a screenshot of what I see when the issue happens:
Image
  1. Some related code snippets — the reply message is sent successfully, but the inline buttons are not when the error occurs.
type TgBot struct {
	InternalBot *telegramBotApi.Bot
	ctx         context.Context
}

func NewTgBot(token string, ctx context.Context) (*TgBot, error) {
        // import telegramBotApi "github.com/go-telegram/bot"
	bot, err := telegramBotApi.New(token)

	if err != nil {
		return nil, err
	}
	return &TgBot{
		InternalBot: bot,
		ctx:         ctx,
	}, nil
}

func (that *TgBot) GetUsername() (string, error) {
	me, err := that.GetMe()
	if err != nil {
		return "", err
	}

	return me.Username, nil
}

func (that *TgBot) GetMe() (*models.User, error) {
	me, err := that.InternalBot.GetMe(that.ctx)

	return me, err
}

func getDefaultButtons(b *tg_bot.TgBot) models.ReplyMarkup {
	username, err := b.GetUsername()
	if err != nil {
               // logged via zap in my project
		logger.Error("Cannot get bot username", zap.Error(err))
		return nil
	}
	buttons := [][]models.InlineKeyboardButton{
		{
			{Text: "deposit", URL: fmt.Sprintf("https://t.me/%s?start=deposit", username)},
		},
	}

	return &models.InlineKeyboardMarkup{InlineKeyboard: buttons}
}

func sendBetConfirmReply(b *tg_bot.TgBot, chatID int64, replyToMessageID int, playerName string, newBalance float64, bets []*model.GameBet) {
	confirmMsg := fmt.Sprintf("<b>%s</b> success, balance is %.2f: \n", playerName, newBalance)
	for _, be := range bets {
		aliasStr := bet_rule.TranslateAlias(&bet_rule.BetData{
			BetOption: be.BetOption,
			BetAmount: be.BetAmount,
		})

		confirmMsg += fmt.Sprintf("- %s\n", aliasStr)
	}

	err := b.SendReplyMsg(confirmMsg, chatID, replyToMessageID, getDefaultButtons(b))

	if err != nil {
		logger.Error("Failed to send confirmation message", zap.Error(err))
	}
}

g-mero avatar Oct 30 '25 05:10 g-mero

@g-mero

I think I understand. It looks like an expected feature of the http2 protocol, rather than a problem with the go-telegram library. A similar topic was raised in this thread on the main Go repository: https://github.com/golang/go/issues/62453.

In short, an http2 connection cannot be “infinite” and will close sooner or later. Consequently, any attempt to make a request over this connection will fail with “GOAWAY.”


From the library's side, I think it would be possible to implement more adaptive retry logic for such cases. But this requires careful design and testing, so I don't think it will be done anytime soon.

It seems that for now, the only option is to accept this error as “expected due to the expiration of the http2 connection timeout.”

steindvart avatar Oct 30 '25 06:10 steindvart