@@ -348,21 +348,19 @@ def _check_rest_response_for_error(
348348 response_data: Raw response data
349349
350350 Raises:
351- RequestError: If the response indicates an error
351+ Various exceptions based on the error type
352352 """
353353 if status_code >= 400 :
354354 error_message = f"REST HTTP request failed with status { status_code } "
355355 error_code = None
356-
356+
357357 # Try to extract error details from JSON response
358358 if response_data :
359359 try :
360360 error_details = json .loads (response_data .decode ("utf-8" ))
361361 if isinstance (error_details , dict ):
362362 if "message" in error_details :
363- error_message = (
364- f"{ error_message } : { error_details ['message' ]} "
365- )
363+ error_message = f"{ error_message } : { error_details ['message' ]} "
366364 if "error_code" in error_details :
367365 error_code = error_details ["error_code" ]
368366 elif "errorCode" in error_details :
@@ -378,68 +376,64 @@ def _check_rest_response_for_error(
378376 logger .error (f"Request failed (status { status_code } ): No response data" )
379377
380378 from databricks .sql .exc import (
381- RequestError ,
382- OperationalError ,
379+ RequestError ,
380+ OperationalError ,
383381 DatabaseError ,
384382 SessionAlreadyClosedError ,
385383 CursorAlreadyClosedError ,
384+ NonRecoverableNetworkError ,
385+ UnsafeToRetryError
386386 )
387-
388- # Map status codes to appropriate exceptions to match Thrift behavior
387+
388+ # Map HTTP status codes to appropriate exceptions
389389 if status_code == 429 :
390- # Rate limiting errors
390+ # Rate limiting errors - similar to what ThriftDatabricksClient does
391391 retry_after = None
392392 if self .headers and "Retry-After" in self .headers :
393393 retry_after = self .headers ["Retry-After" ]
394-
394+
395395 rate_limit_msg = f"Maximum rate has been exceeded. Please reduce the rate of requests and try again"
396396 if retry_after :
397397 rate_limit_msg += f" after { retry_after } seconds."
398398 raise RequestError (rate_limit_msg )
399-
399+
400400 elif status_code == 503 :
401401 # Service unavailable errors
402- raise OperationalError (
403- "TEMPORARILY_UNAVAILABLE: Service temporarily unavailable"
404- )
405-
402+ raise OperationalError ("TEMPORARILY_UNAVAILABLE: Service temporarily unavailable" )
403+
406404 elif status_code == 404 :
407405 # Not found errors - could be session or operation already closed
408406 if error_message and "session" in error_message .lower ():
409- raise SessionAlreadyClosedError (
410- "Session was closed by a prior request"
411- )
412- elif error_message and (
413- "operation" in error_message .lower ()
414- or "statement" in error_message .lower ()
415- ):
416- raise CursorAlreadyClosedError (
417- "Operation was canceled by a prior request"
418- )
407+ raise SessionAlreadyClosedError ("Session was closed by a prior request" )
408+ elif error_message and ("operation" in error_message .lower () or "statement" in error_message .lower ()):
409+ raise CursorAlreadyClosedError ("Operation was canceled by a prior request" )
419410 else :
420411 raise RequestError (error_message )
421-
412+
422413 elif status_code == 401 :
423414 # Authentication errors
424- raise OperationalError (
425- "Authentication failed. Please check your credentials."
426- )
427-
415+ raise OperationalError ("Authentication failed. Please check your credentials." )
416+
428417 elif status_code == 403 :
429418 # Permission errors
430- raise OperationalError (
431- "Permission denied. You do not have access to this resource."
432- )
433-
419+ raise OperationalError ("Permission denied. You do not have access to this resource." )
420+
434421 elif status_code == 400 :
435422 # Bad request errors - often syntax errors
436423 if error_message and "syntax" in error_message .lower ():
437- raise DatabaseError (
438- f"Syntax error in SQL statement: { error_message } "
439- )
424+ raise DatabaseError (f"Syntax error in SQL statement: { error_message } " )
440425 else :
441426 raise RequestError (error_message )
442-
427+
428+ elif status_code == 501 :
429+ # Not implemented errors
430+ raise NonRecoverableNetworkError (f"Not implemented: { error_message } " )
431+
432+ elif status_code == 502 or status_code == 504 :
433+ # Bad gateway or gateway timeout errors
434+ # These are considered dangerous to retry for ExecuteStatement
435+ raise UnsafeToRetryError (f"Gateway error: { error_message } " )
436+
443437 else :
444438 # Generic errors
445439 raise RequestError (error_message )
0 commit comments