In cbsonmodule.c under the case 7 (ObjectID) switch, a call is made to PyObject_GetAttrString(value, "_ObjectIdid") instead of PyBytes_AsString requesting Python cast the ObjectId value to a byte string. Interestingly, it does use PyBytes immediately after retrieval of the private attribute. By utilizing that private (mangled) attribute, it requires extremely ugly hacks in any datatype one attempts to write that must be compatible. Please consider implementing bytes within ObjectId (it's curiously missing despite str_ being present!) and utilizing the standard, less-private interface. Thanks!