Uploaded image for project: 'Go Driver'
  1. Go Driver
  2. GODRIVER-1005

Decoding SingleResult or cursor to nil pointer type panics

    • Type: Icon: Bug Bug
    • Resolution: Fixed
    • Priority: Icon: Major - P3 Major - P3
    • 1.0.2
    • Affects Version/s: 1.0.1
    • Component/s: None
    • Labels:
      None
    • Fully Compatible

      Decoding to a nil pointer of a type panics.

      This pattern works:

      struct X {}
      var x X
      res.Decode(&x)
      

      This pattern panics:

      var x *X
      res.Decode(x)
      

      This is subtle and users are likely to mess this up. We should detect this condition and return an instructive error instead of panicking and should document this limitation clearly.

      We do this for other usage errors, such as "argument to Decode must be a pointer to a type, but got map[]".

      Sample program:

      package main
      
      import (
      	"context"
      	"fmt"
      	"log"
      
      	"go.mongodb.org/mongo-driver/bson"
      	"go.mongodb.org/mongo-driver/bson/primitive"
      	"go.mongodb.org/mongo-driver/mongo"
      )
      
      type X struct {
      	ID   primitive.ObjectID `bson:"_id,omitempty"`
      	Name string             `bson:"name"`
      }
      
      func main() {
      	ctx := context.Background()
      
      	client, err := mongo.Connect(ctx)
      	if err != nil {
      		log.Fatal(err)
      	}
      
      	coll := client.Database("test").Collection("decodeit")
      	_ = coll.Drop(ctx)
      
      	doc := X{Name: "hello world"}
      	res, err := coll.InsertOne(ctx, doc)
      	if err != nil {
      		log.Fatal(err)
      	}
      	id := res.InsertedID
      	fmt.Println("Inserted", id)
      
      	got := coll.FindOne(ctx, bson.D{{"_id", id}})
      	if got.Err() != nil {
      		log.Fatal(got.Err())
      	}
      
      	var doc2 *X
      	err = got.Decode(doc2)
      	if err != nil {
      		log.Fatalf("doc2 %v", err)
      	}
      	fmt.Println("doc2", *doc2)
      }
      

      Output:

      $ go run main.go
      Inserted ObjectID("5cc65cd9731bafcc96ccb4f3")
      panic: reflect: call of reflect.Value.Type on zero Value
      
      goroutine 1 [running]:
      reflect.Value.Type(0x0, 0x0, 0x0, 0x0, 0x0)
              /usr/local/go/src/reflect/value.go:1813 +0x169
      go.mongodb.org/mongo-driver/bson.(*Decoder).Decode(0xc000083cb0, 0x140ce60, 0x0, 0x14567e0, 0xc000083cb0)
              /Users/david/golang/pkg/mod/go.mongodb.org/mongo-driver@v1.0.1/bson/decoder.go:82 +0x25d
      go.mongodb.org/mongo-driver/bson.unmarshalFromReader(0xc0000c2070, 0xc00005e400, 0x0, 0x0, 0x15f6ae0, 0xc00005e480, 0x140ce60, 0x0, 0x0, 0x0)
              /Users/david/golang/pkg/mod/go.mongodb.org/mongo-driver@v1.0.1/bson/unmarshal.go:100 +0xff
      go.mongodb.org/mongo-driver/bson.UnmarshalWithRegistry(0xc0000c2070, 0xc0000ce223, 0x2c, 0x5d, 0x140ce60, 0x0, 0x0, 0x0)
              /Users/david/golang/pkg/mod/go.mongodb.org/mongo-driver@v1.0.1/bson/unmarshal.go:45 +0x10a
      go.mongodb.org/mongo-driver/mongo.(*Cursor).Decode(...)
              /Users/david/golang/pkg/mod/go.mongodb.org/mongo-driver@v1.0.1/mongo/cursor.go:123
      go.mongodb.org/mongo-driver/mongo.(*SingleResult).Decode(0xc00005e440, 0x140ce60, 0x0, 0x0, 0x0)
              /Users/david/golang/pkg/mod/go.mongodb.org/mongo-driver@v1.0.1/mongo/single_result.go:59 +0x197
      main.main()
              /Users/david/tmp/godriver-decode-pointer/main.go:43 +0x426
      exit status 2
      

            Assignee:
            divjot.arora@mongodb.com Divjot Arora (Inactive)
            Reporter:
            david.golden@mongodb.com David Golden
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: