@@ -96,7 +96,7 @@ public struct InternalError: RuntimeError {
9696/// An error thrown when encountering a connection or socket related error.
9797/// May contain labels providing additional information on the nature of the error.
9898public struct ConnectionError : RuntimeError , LabeledError {
99- internal let message : String
99+ public let message : String
100100
101101 public let errorLabels : [ String ] ?
102102
@@ -173,11 +173,36 @@ public struct WriteConcernFailure: Codable {
173173 /// A description of the error.
174174 public let message : String
175175
176+ /// Labels that may describe the context in which this error was thrown.
177+ public let errorLabels : [ String ] ?
178+
176179 private enum CodingKeys : String , CodingKey {
177180 case code
178181 case codeName
179182 case details = " errInfo "
180183 case message = " errmsg "
184+ case errorLabels
185+ }
186+
187+ // TODO: can remove this once SERVER-36755 is resolved
188+ public init ( from decoder: Decoder ) throws {
189+ let container = try decoder. container ( keyedBy: CodingKeys . self)
190+ self . code = try container. decode ( ServerErrorCode . self, forKey: . code)
191+ self . message = try container. decode ( String . self, forKey: . message)
192+ self . codeName = try container. decodeIfPresent ( String . self, forKey: . codeName) ?? " "
193+ self . details = try container. decodeIfPresent ( Document . self, forKey: . details)
194+ self . errorLabels = try container. decodeIfPresent ( [ String ] . self, forKey: . errorLabels)
195+ }
196+
197+ // TODO: can remove this once SERVER-36755 is resolved
198+ internal init (
199+ code: ServerErrorCode , codeName: String , details: Document ? , message: String , errorLabels: [ String ] ? = nil
200+ ) {
201+ self . code = code
202+ self . codeName = codeName
203+ self . message = message
204+ self . details = details
205+ self . errorLabels = errorLabels
181206 }
182207}
183208
@@ -279,6 +304,7 @@ internal func extractMongoError(error bsonError: bson_error_t, reply: Document?
279304 // if the reply is nil or writeErrors or writeConcernErrors aren't present, then this is likely a commandError.
280305 guard let serverReply: Document = reply,
281306 !( serverReply [ " writeErrors " ] ? . arrayValue ?? [ ] ) . isEmpty ||
307+ !( serverReply [ " writeConcernError " ] ? . documentValue? . keys ?? [ ] ) . isEmpty ||
282308 !( serverReply [ " writeConcernErrors " ] ? . arrayValue ?? [ ] ) . isEmpty else {
283309 return parseMongocError ( bsonError, reply: reply)
284310 }
@@ -390,11 +416,14 @@ internal func extractBulkWriteError<T: Codable>(
390416
391417/// Extracts a `WriteConcernError` from a server reply.
392418private func extractWriteConcernError( from reply: Document ) throws -> WriteConcernFailure ? {
393- guard let writeConcernErrors = reply [ " writeConcernErrors " ] ? . arrayValue? . compactMap ( { $0. documentValue } ) ,
394- !writeConcernErrors. isEmpty else {
419+ if let writeConcernErrors = reply [ " writeConcernErrors " ] ? . arrayValue? . compactMap ( { $0. documentValue } ) ,
420+ !writeConcernErrors. isEmpty {
421+ return try BSONDecoder ( ) . decode ( WriteConcernFailure . self, from: writeConcernErrors [ 0 ] )
422+ } else if let writeConcernError = reply [ " writeConcernError " ] ? . documentValue {
423+ return try BSONDecoder ( ) . decode ( WriteConcernFailure . self, from: writeConcernError)
424+ } else {
395425 return nil
396426 }
397- return try BSONDecoder ( ) . decode ( WriteConcernFailure . self, from: writeConcernErrors [ 0 ] )
398427}
399428
400429/// Internal function used by write methods performing single writes that are implemented via the bulk API. If the
0 commit comments