Check the response to a command for errors.
(
response: _DocumentOut,
max_wire_version: Optional[int],
allowable_errors: Optional[Container[Union[int, str]]] = None,
parse_write_concern_error: bool = False,
pool_opts: Optional[PoolOptions] = None,
)
| 213 | |
| 214 | |
| 215 | def _check_command_response( |
| 216 | response: _DocumentOut, |
| 217 | max_wire_version: Optional[int], |
| 218 | allowable_errors: Optional[Container[Union[int, str]]] = None, |
| 219 | parse_write_concern_error: bool = False, |
| 220 | pool_opts: Optional[PoolOptions] = None, |
| 221 | ) -> None: |
| 222 | """Check the response to a command for errors.""" |
| 223 | if "ok" not in response: |
| 224 | # Server didn't recognize our message as a command. |
| 225 | raise OperationFailure( |
| 226 | response.get("$err"), # type: ignore[arg-type] |
| 227 | response.get("code"), |
| 228 | response, |
| 229 | max_wire_version, |
| 230 | ) |
| 231 | |
| 232 | if parse_write_concern_error and "writeConcernError" in response: |
| 233 | _error = response["writeConcernError"] |
| 234 | _labels = response.get("errorLabels") |
| 235 | if _labels: |
| 236 | _error.update({"errorLabels": _labels}) |
| 237 | _raise_write_concern_error(_error) |
| 238 | |
| 239 | if response["ok"]: |
| 240 | return |
| 241 | |
| 242 | details = response |
| 243 | # Mongos returns the error details in a 'raw' object |
| 244 | # for some errors. |
| 245 | if "raw" in response: |
| 246 | for shard in response["raw"].values(): |
| 247 | # Grab the first non-empty raw error from a shard. |
| 248 | if shard.get("errmsg") and not shard.get("ok"): |
| 249 | details = shard |
| 250 | break |
| 251 | |
| 252 | errmsg = details["errmsg"] |
| 253 | code = details.get("code") |
| 254 | |
| 255 | # For allowable errors, only check for error messages when the code is not |
| 256 | # included. |
| 257 | if allowable_errors: |
| 258 | if code is not None: |
| 259 | if code in allowable_errors: |
| 260 | return |
| 261 | elif errmsg in allowable_errors: |
| 262 | return |
| 263 | |
| 264 | # Server is "not primary" or "recovering" |
| 265 | if code is not None: |
| 266 | if code in _NOT_PRIMARY_CODES: |
| 267 | raise NotPrimaryError(errmsg, response) |
| 268 | elif HelloCompat.LEGACY_ERROR in errmsg or "node is recovering" in errmsg: |
| 269 | raise NotPrimaryError(errmsg, response) |
| 270 | |
| 271 | # Other errors |
| 272 | # findAndModify with upsert can raise duplicate key error |