Question about nil pointer dereference error in encoding/json

Hi Everyone,

We are using the json encoder from golang (we are using version 1.21) and we sometimes get the following nil pointer error when marshalling a very simple struct:

goroutine 1619784 [running]:
panic: runtime error: invalid memory address or nil pointer dereference [recovered]
panic: runtime error: invalid memory address or nil pointer dereference
encoding/json.(*encodeState).marshal.func1()
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x5580e728fe0b]
    /usr/lib/golang/src/encoding/json/encode.go:293 +0x6d
    /usr/lib/golang/src/encoding/json/encode.go:321 +0x73
encoding/json.stringEncoder(0xc00378c080, {0x5580e7e1aea0?, 0xc003d06200?, 0xc002b1600a?}, {0x19?, 0x0?})
    /usr/lib/golang/src/encoding/json/encode.go:704 +0x21e
    /usr/lib/golang/src/encoding/json/encode.go:321 +0x73
encoding/json.ptrEncoder.encode({0x5580e7d912c8?}, 0xc00378c080, {0x5580e7dfc600?, 0xc000e22cc0?, 0x5580e7dfc600?}, {0x10?, 0x0?})
    /usr/lib/golang/src/encoding/json/encode.go:876 +0x23c
    /usr/lib/golang/src/encoding/json/encode.go:847 +0xcf
encoding/json.structEncoder.encode({{{0xc0018d8240, 0x1, 0x1}, 0xc001880480, 0xc0018804b0}}, 0xc00378c080, {0x5580e7ead360?, 0xc003d06200?, 0xc003d06200?}, {0x0, ...})
encoding/json.(*encodeState).marshal(0xc001b319c8?, {0x5580e7dfc600?, 0xc000e22cc0?}, {0x2f?, 0x0?})
encoding/json.ptrEncoder.encode({0x7f06d8fc28b8?}, 0xc00378c080, {0x5580e7df0540?, 0xc003d06200?, 0x5580e7df0540?}, {0x60?, 0xce?})
    /usr/lib/golang/src/encoding/json/encode.go:876 +0x23c
encoding/json.arrayEncoder.encode({0xc0021ba360?}, 0xc00378c080, {0x5580e7e2f0c0?, 0xc000e22cd0?, 0x5580e7e1aea0?}, {0x9?, 0x0?})
    /usr/lib/golang/src/encoding/json/encode.go:658 +0xba
    /usr/lib/golang/src/encoding/json/encode.go:960 +0xab
panic({0x5580e7e7e7a0?, 0x5580e86125a0?})
    /usr/lib/golang/src/runtime/panic.go:770 +0x132
encoding/json.(*encodeState).reflectValue(0xc00378c080, {0x5580e7df0540?, 0xc003d06200?, 0x5580e727c825?}, {0x40?, 0x16?})
encoding/json.interfaceEncoder(0xc00378c080, {0x5580e7e50fe0?, 0xc000e22cd0?, 0x1?}, {0xa0?, 0xae?})
encoding/json.structEncoder.encode({{{0xc000b40008, 0x3, 0x4}, 0xc0008a6f00, 0xc0008a71a0}}, 0xc00378c080, {0x5580e7f02cc0?, 0xc000e22cc0?, 0xc000e22cc0?}, {0x0, ...})
    /usr/lib/golang/src/encoding/json/encode.go:589 +0x3c7
encoding/json.appendString[...]({0xc001eec0b6?, 0x10?, 0x7f0720605f48?}, {0x0?, 0x40}, 0x1)
encoding/json.(*encodeState).reflectValue(0xc00378c080, {0x5580e7dfc600?, 0xc000e22cc0?, 0x12?}, {0x0?, 0xa8?})
    /usr/lib/golang/src/encoding/json/encode.go:704 +0x21e
    /usr/lib/golang/src/encoding/json/encode.go:704 +0x21e
github.com/gorilla/rpc/json.EncodeClientRequest({0x5580e79f5565, 0x17}, {0x5580e7df0540, 0xc003d06200})

We are using encoding/json/json.Marshal() to serialize a very simple function local struct:

&clientRequest{
		Method: method,
		Params: [1]interface{}{args},
		Id:     uint64(rand.Int63()),
	}

The Params is an array that contains just one element, a very simple struct that has just one string inside (that can never be nil as it is not a pointer).

We also call this marshalling logic from multiple go routines at once.

We were not able to pinpoint the source of this error to any issues with our code so far.
So we would like to see if you can give us some hints/advice about what can cause such an error? Are we misusing the json encounter API? Could it be a data race of some sort?

Thank you in advance,
Radu.

Check the Method value.
Also you can use go run -race your_program.go to check data races situations in your code…

maybe more go version info ?

Hi @Rmarian,

Two quick thoughts:

  1. You wrote that “Params is an array that contains just one element, a very simple struct that has just one string inside.”

    Why are you using an array of any (a.k.a. interface{}) rather than an array of the real struct type?

  2. Consider adding a safety check, such as:

    params := [1]interface{}{args}
    if params[0] == nil {
       ...
    

This might help reveal the cause of the nil pointer panic.