Invalid memory address or nil pointer dereference doing HTTP request

Hi, I’m playing around with the Telegram Bot API, using this library. What happens when I attempt to GetUpdates is the following:

panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xb code=0x1 addr=0x10 pc=0x49c0ed]

goroutine 1 [running]:
net/http.(*Client).doFollowingRedirects(0x0, 0xc820162000, 0x866630, 0x0, 0x0, 0x0)
        /usr/lib/go/src/net/http/client.go:313 +0x6d
net/http.(*Client).Post(0x0, 0xc8200bcc00, 0x27, 0x81b380, 0x21, 0x7f8f833a95e0, 0xc8200c05c0, 0xc8200e0230, 0x0, 0x0)
        /usr/lib/go/src/net/http/client.go:471 +0x107
net/http.(*Client).PostForm(0x0, 0xc8200bcc00, 0x27, 0xc8200bcbd0, 0x2, 0x0, 0x0)
        /usr/lib/go/src/net/http/client.go:497 +0x108*BotAPI).MakeRequest(0x987920, 0x7d2e80, 0xa, 0xc8200bcbd0, 0xc8200bcb00, 0x0, 0x0, 0x0, 0x0, 0x0, ...)
        /home/vagrant/goenv/src/ +0x251*BotAPI).GetUpdates(0x987920, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
        /home/vagrant/goenv/src/ +0x501
        /home/vagrant/goenv/src/ +0x80
        /home/vagrant/goenv/src/ +0x3d5

Here’s the code from line 42 to 49:

func GetUpdates() {
	UpdateConfig := tgbotapi.NewUpdate(lastUpdate)
	Updates, err := bot.GetUpdates(UpdateConfig) // L44
	if err != nil {
	go IterateUpdates(Updates)

lastUpdate is an integer containing the highest offset of the updates already received, that is given to the function to avoid getting duplicate updates from the Telegram Bot API.

I sincerely have no clue of what this is happening. I tried to track down to the Go HTTP request library, and this is where the panic seems to be happening:

	func (c *Client) doFollowingRedirects(ireq *Request, shouldRedirect func(int) bool) (resp *Response, err error) {
		var base *url.URL
		redirectChecker := c.CheckRedirect // L313
		if redirectChecker == nil {
			redirectChecker = defaultCheckRedirect

Nothing that suggests why the error is happening, nor how to troubleshoot it.

The incriminated code of the bot library seems to be fine, too:

func (bot *BotAPI) MakeRequest(endpoint string, params url.Values) (APIResponse, error) {
	resp, err := bot.Client.PostForm(fmt.Sprintf(APIEndpoint, bot.Token, endpoint), params) // L197
	if err != nil {
		return APIResponse{}, err
	defer resp.Body.Close()

Where is lastUpdate coming from? Global? GetUpdates() doesn’t accept any params. If it’s invalid (either nil or zero) then I would expect line 44 to return an error and subsequently panic on the if err != nil check.

The Client value is nil, you can see that from the first parameter, 0x0, which is the machine representation of nil.

Whoever is calling PostForm is probably missing an error check.


It does?

(Oh yeah, now I see what you mean. Sorry for the confusion - there are two GetUpdates method, one in my code, in the package main, and is the one I wrote, while there’s a second in the bot API, which does take a parameter)

Doesn’t seem so.

Correct: I mean yours. Where does the lastUpdate value come from if it’s not passed in as a function param?

It is, as you said, global.

var lastUpdate int = 0

Changing it to 1 doesn’t do anything - error keeps happening. Even changing the call tgbotapi.NewUpdate to pass 1 directly doesn’t fix it.

Your botapi receiver is nil

bot.Client is nil. There is no check


Thank you so much!

The solution, I found out thanks to what you purposed, was actually about removing a single character in some code I didn’t show (I regret not doing it, as it probably would have led to the solution faster).

I just so happened to do this in the main function:

bot, err := tgbotapi.NewBotAPI(conf.Token)

I was creating a new variable containing the bot client only available in the main function. So the solution, was simply removing the ::

bot, err = tgbotapi.NewBotAPI(conf.Token)

A common error already mentioned in this thread

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.