Docs Menu
Docs Home
/ / /
Go Driver

FAQ

On this page

  • Why Am I Getting Errors While Connecting to MongoDB?
  • How Does Connection Pooling Work in the Go driver?
  • How Can I Fix the "WriteNull can only write while positioned on a Element or Value but is positioned on a TopLevel" Error?
  • How Do I Convert a BSON Document to JSON?

This page contains frequently asked questions and their corresponding answers.

Tip

If you can't find an answer to your problem on this page, see the Issues & Help page for next steps and more resources.

If you have trouble connecting to a MongoDB deployment, see the Connection Troubleshooting Guide for possible solutions.

Every Client instance has a built-in connection pool for each server in your MongoDB topology. Connection pools open sockets on demand to support concurrent MongoDB operations, or goroutines, in your application.

The maximum size of each connection pool is set by the maxPoolSize option, which defaults to 100. If the number of in-use connections to a server reaches the value of maxPoolSize, the next request to that server will wait until a connection becomes available.

The Client instance opens two additional sockets per server in your MongoDB topology for monitoring the server's state.

For example, a client connected to a 3-node replica set opens 6 monitoring sockets. It also opens the necessary sockets to support an application's concurrent operations on each server, up to the value of maxPoolSize. If maxPoolSize is 100 and the application only uses the primary (the default), then only the primary connection pool grows and there can be at most 106 total connections. If the application uses a read preference to query the secondary nodes, their pools also grow and there can be 306 total connections.

Additionally, connection pools are rate-limited such that each connection pool can only create, at maximum, the value of maxConnecting connections in parallel at any time. Any additional goroutine stops waiting in the following cases:

  • One of the existing goroutines finishes creating a connection, or an existing connection is checked back into the pool.

  • The driver's ability to reuse existing connections improves due to rate-limits on connection creation.

You can set the minimum number of concurrent connections to each server by using the minPoolSize option, which defaults to 0. After setting minPoolSize, the connection pool is initialized with this number of sockets. If sockets close due to any network errors, causing the total number of sockets (both in use and idle) to drop below the minimum, more sockets open until the minimum is reached.

You can set the maximum number of milliseconds that a connection can remain idle in the pool before being removed and replaced with the maxIdleTimeMS option, which defaults to None (no limit).

The following default configuration for a Client works for most applications:

client := mongo.Connect(context.TODO(), "<connection string>")

Create a client once for each process, and reuse it for all operations. It is a common mistake to create a new client for each request, which is very inefficient.

To support high numbers of concurrent MongoDB operations within one process, you can increase maxPoolSize. Once the pool reaches its maximum size, additional operations wait for sockets to become available.

The driver does not limit the number of operations that can wait for sockets to become available and it is the application's responsibility to limit the size of its pool to bound queuing during a load spike. Operations can wait for any length of time unless you define the waitQueueTimeoutMS option.

An operation that waits more than the length of time defined by waitQueueTimeoutMS for a socket raises a connection error. Use this option if it is more important to bound the duration of operations during a load spike than it is to complete every operation.

When Client.Disconnect() is called by any goroutine, the driver closes all idle sockets and closes all sockets that are in use as they are returned to the pool.

The bson.Marshal() method requires a parameter that can be decoded into a BSON document, such as the bson.D type. This error occurs when you pass something other than a BSON document to bson.Marshal().

The WriteNull error occurs when you pass a null to bson.Marshal(). Situations in which a similar error can occur include the following:

  • You pass a string to bson.Marshal(), causing a WriteString error.

  • You pass a boolean to bson.Marshal(), causing a WriteBoolean error.

  • You pass an integer to bson.Marshal(), causing a WriteInt32 error.

You may encounter this error when you perform a CRUD operation that internally uses the bson.Marshal() method or when you call bson.Marshal() directly to encode data.

The following code produces a WriteNull error because the driver cannot encode the null value of sortOrder to BSON during the FindOneAndUpdate() operation:

var sortOrder bson.D
opts := options.FindOneAndUpdate().SetSort(sortOrder)
updateDocument := bson.D{{"$inc", bson.D{{"counter", 1}}}}
result := coll.FindOneAndUpdate(context.TODO(), bson.D{}, updateDocument, opts)
if err := result.Err(); err != nil {
panic(err)
}

The following code shows how to correctly initialize the sortOrder variable as a bson.D type so that the driver can convert it to BSON:

sortOrder := bson.D{}

The driver provides a variety of marshaler methods that can be used to convert a BSON document to JSON, such as the MarshalExtJSON() method. To view a readable form of the JSON encoding, you must use an unmarshaler method or string type-casting to parse the JSON byte format.

The following code converts a BSON document to JSON using the MarshalExtJSON() method, then parses and prints the JSON byte array using string type-casting:

bsonDocument := bson.D{{"hello", "world"}}
jsonBytes, err := bson.MarshalExtJSON(bsonDocument, true, false)
if err != nil {
panic(err)
}
fmt.Println(string(jsonBytes))
{"hello":"world"}

To learn more about conversions between BSON and Go types, see the Work with BSON guide.

Back

Geospatial Data