getLastError Command

MongoDB does not wait for a response by default when writing to the database. Use the getLastError command to ensure that operations have succeeded.

Many of the drivers can invoke the getLastError command automatically on a write operation. Enabling this driver option is called "safe mode" ("write concern" in some drivers). When enabled, the driver piggybacks a getLastError message with each write message. It then awaits the result of the getLastError command before returning.

A few other alternative modes of operation exist. First, an application could not call getLastError at all. This might be appropriate if, for example, one is writing data to a log, and would not report the error to the user anyway. Another option would be to only call getLastError after a series of operations.

Running in the Shell

The getlasterror command checks for an error on the last database operation for this connection. Since it's a command, there are a few ways to invoke it:

> db.$cmd.findOne({getlasterror:1})

Or in the shell:

> db.runCommand("getlasterror")

Or you can use the shell helper:

> db.getLastError()

In the mongo shell, db.getLastError() returns the last error – null if no error. Use db.getLastErrorObj() to see the full error result. db.getLastErrorObj().err should be null if there is no error condition.

For more about commands, see the command documentation.

When to Use

getlasterror is primarily useful for write operations (although it is set after a command or query too).  Write operations by default do not have a return code: this saves the client from waiting for client/server turnarounds during write operations.  One can always call getLastError if one wants a return code.

If you're writing data to MongoDB on multiple connections, then it can sometimes be important to call getlasterror on one connection to be certain that the data has been committed to the database. For instance, if you're writing to connection #1 and want those writes to be reflected in reads from connection #2, you can assure this by calling getlasterror after writing to connection #1.

For maximum speed, skip the getLastError (or "safe mode") for noncritical writes. Use it when you need to confirm to the user that the write succeeded.

Options

j

v2.0+: When j:true is specified, the getlasterror call awaits the journal commit before returning. If the server is running without journaling, it returns immediately, and successfully.

> db.runCommand({getlasterror:1,j:true})

w

A client can block until a write operation has been replicated to N servers.

wtimeout may be used in conjunction with w. The default is no timeout (wait forever).

> db.getLastError(2, 5000) // w=2, timeout 5000ms

Note the above options can be combined: waiting for journal acknowledgement and acknowledgement that the write has reached a majority of a replica set can make sense.

Tagging And Majority

Now with MongoDB 2.0 there is the ability to control which nodes are written to. Instead of specifying the number of nodes which a write must be acknowledged by, you can specify rules based on tags in the configuration.

In addition to the tagging rules you can also specify a string of "majority":

>db.getLastError("majority") // waits for more than 50% of the configured nodes to acknowledge the write (until replication is applied to the point of that write)

fsync

When running mongod without journaling (--nojournal), the fsync option forces the database to fsync all files before returning.

When running with journaling, the fsync option awaits the next group commit before returning.

> db.runCommand({getlasterror:1,fsync:true})
{ "err" : null, "n" : 0, "fsyncFiles" : 2, "ok" : 1 }

Use j, not fsync.

Combining

A good combination for highly critical writes is j:true and w:"majority".

Return Value

The return value from the command is an object with various fields. The common fields are listed below; there may also be other fields.

  • ok - true indicates the getLastError command completed successfully. This does NOT indicate there wasn't a last error.
  • err - if non-null, indicates an error occurred. Value is a textual description of the error.
  • code - if set, indicates the error code which occurred.
  • connectionId - the id of the connection
  • lastOp - the op-id from the last operation

For updates:

  • n - if an update was done, this is the number of documents updated.

With w:<n>/<tag>

  • wnote - if set indicates that something unusual happened that is related to using w:
  • wtimeout - if timed out, set to the value true
  • waited - if timed out, how long waited in milliseconds
  • wtime - the time spent waiting for the operation to complete

Using getLastError from Drivers

The drivers support getLastError in the command form and many also offer a "safe" mode for operations. For more on "safe" mode, see each driver's documentation.

* C#

  • C++
  • Python. If you're using Python, you automatically call getlasterror on insert as follows:
    collection.save({"name": "MongoDB"}, safe=True)

    If the save doesn't succeed, an exception will be raised.

  • Java
    Java supports various getLastError() semantics using WriteConcern Objects.

Mongo Shell REPL Behavior

The database shell performs a resetError() before each read/eval/print loop command evaluation - and automatically prints the error, if one occurred, after each evaluation. Thus, after an error, at the shell prompt db.getLastError() will return null. However, if called before returning to the prompt, the result is as one would expect:

> try { db.foo.findOne() } catch(e) { print("preverr:" + tojson(db.getPrevError())); print("lasterr:" + tojson(db.getLastError()));}
preverr:{"err" : "unauthorized" , "nPrev" : 1 , "ok" : 1}
lasterr:"unauthorized"

getPrevError Command

When performing bulk write operations, resetError() and getPrevError() can be an efficient way to check for success of the operation.  For example if we are inserting 1,000 objects in a collection, checking the return code 1,000 times over the network is slow.  Instead one might do something like this:

db.resetError(); 
for( loop 1000 times... )
    db.foo.save(something...);
if( db.getPrevError().err ) 
    print("didn't work!");
  • getPrevError only holds 1 previous error, so whole batch may have to be retried in case of error.
  • A better alternative is to use the "batch" insert method provided by many drivers, along with safe writes. This way "getLastError" is only called after each batch, but still writes will stop at the 1st error.
  • getPrevError may be deprecated in the future.

See Also

Follow @mongodb

MongoDB Pittsburgh - May 15
MongoNYC - May 23
MongoDB Paris - Jun 14
MongoDB UK - Jun 20
MongoDC - June 26


Labels

command command Delete
getlasterror getlasterror Delete
Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.

PLEASE POST QUESTIONS IN THE USER GROUPS FORUM. Post non-question comments and helpful hints here.

blog comments powered by Disqus