Skip to content

Commit 9cd613b

Browse files
committed
SK-1934 Fix inconsistent error handling for invoke connections
1 parent 74628e5 commit 9cd613b

File tree

5 files changed

+34
-25
lines changed

5 files changed

+34
-25
lines changed

skyflow/utils/_skyflow_messages.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,7 @@ class ErrorLogs(Enum):
275275
UPDATE_REQUEST_REJECTED = f"{ERROR}: [{error_prefix}] Update request resulted in failure."
276276
QUERY_REQUEST_REJECTED = f"{ERROR}: [{error_prefix}] Query request resulted in failure."
277277
GET_REQUEST_REJECTED = f"{ERROR}: [{error_prefix}] Get request resulted in failure."
278+
INVOKE_CONNECTION_REQUEST_REJECTED = f"{ERROR}: [{error_prefix}] Invoke connection request resulted in failure."
278279

279280
class Interface(Enum):
280281
INSERT = "INSERT"

skyflow/utils/_utils.py

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -327,29 +327,30 @@ def parse_invoke_connection_response(api_response: requests.Response):
327327

328328
invoke_connection_response.response = json_content
329329
return invoke_connection_response
330-
except:
330+
except Exception as e:
331331
raise SkyflowError(SkyflowMessages.Error.RESPONSE_NOT_JSON.value.format(content), status_code)
332332
except HTTPError:
333-
message = SkyflowMessages.Error.API_ERROR.value.format(status_code)
334-
if api_response and api_response.content:
335-
try:
336-
error_response = json.loads(content)
337-
if isinstance(error_response.get('error'), dict) and 'message' in error_response['error']:
338-
message = error_response['error']['message']
339-
except json.JSONDecodeError:
340-
message = SkyflowMessages.Error.RESPONSE_NOT_JSON.value.format(content)
341-
342-
if 'x-request-id' in api_response.headers:
343-
message += ' - request id: ' + api_response.headers['x-request-id']
344-
345-
if 'error-from-client' in api_response.headers:
346-
error_from_client = api_response.headers['error-from-client']
347-
details = [{ "error_from_client": error_from_client }]
348-
raise SkyflowError(message, status_code, details=details)
349-
333+
message = SkyflowMessages.Error.API_ERROR.value.format(status_code)
334+
try:
335+
error_response = json.loads(content)
336+
request_id = api_response.headers['x-request-id']
337+
error_from_client = api_response.headers.get('error-from-client')
338+
339+
status_code = error_response.get('error', {}).get('http_code', 500) # Default to 500 if not found
340+
http_status = error_response.get('error', {}).get('http_status')
341+
grpc_code = error_response.get('error', {}).get('grpc_code')
342+
details = error_response.get('error', {}).get('details')
343+
message = error_response.get('error', {}).get('message', "An unknown error occurred.")
344+
345+
if error_from_client is not None:
346+
if details is None: details = []
347+
details.append({'error_from_client': error_from_client})
348+
349+
raise SkyflowError(message, status_code, request_id, grpc_code, http_status, details)
350+
except json.JSONDecodeError:
351+
message = SkyflowMessages.Error.RESPONSE_NOT_JSON.value.format(content)
350352
raise SkyflowError(message, status_code)
351353

352-
353354
def log_and_reject_error(description, status_code, request_id, http_status=None, grpc_code=None, details=None, logger = None):
354355
raise SkyflowError(description, status_code, request_id, grpc_code, http_status, details)
355356

skyflow/vault/controller/_connections.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from skyflow.error import SkyflowError
44
from skyflow.utils import construct_invoke_connection_request, SkyflowMessages, get_metrics, \
55
parse_invoke_connection_response
6-
from skyflow.utils.logger import log_info
6+
from skyflow.utils.logger import log_info, log_error_log
77
from skyflow.vault.connection import InvokeConnectionRequest
88

99

@@ -36,6 +36,7 @@ def invoke(self, request: InvokeConnectionRequest):
3636
return invoke_connection_response
3737

3838
except Exception as e:
39+
log_error_log(SkyflowMessages.ErrorLogs.INVOKE_CONNECTION_REQUEST_REJECTED.value, self.__vault_client.get_logger())
3940
if isinstance(e, SkyflowError): raise e
4041
raise SkyflowError(SkyflowMessages.Error.INVOKE_CONNECTION_FAILED.value,
4142
SkyflowMessages.ErrorCodes.SERVER_ERROR.value)

tests/utils/test__utils.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,8 @@ def test_parse_invoke_connection_response_http_error_with_json_error_message(sel
344344
with self.assertRaises(SkyflowError) as context:
345345
parse_invoke_connection_response(mock_response)
346346

347-
self.assertEqual(context.exception.message, "Not Found - request id: 1234")
347+
self.assertEqual(context.exception.message, "Not Found")
348+
self.assertEqual(context.exception.request_id, "1234")
348349

349350
@patch("requests.Response")
350351
def test_parse_invoke_connection_response_http_error_without_json_error_message(self, mock_response):
@@ -357,7 +358,7 @@ def test_parse_invoke_connection_response_http_error_without_json_error_message(
357358
with self.assertRaises(SkyflowError) as context:
358359
parse_invoke_connection_response(mock_response)
359360

360-
self.assertEqual(context.exception.message, SkyflowMessages.Error.RESPONSE_NOT_JSON.value.format("Internal Server Error") + " - request id: 1234")
361+
self.assertEqual(context.exception.message, SkyflowMessages.Error.RESPONSE_NOT_JSON.value.format("Internal Server Error"))
361362

362363
@patch("skyflow.utils._utils.log_and_reject_error")
363364
def test_handle_exception_json_error(self, mock_log_and_reject_error):

tests/vault/controller/test__connection.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from skyflow.error import SkyflowError
55
from skyflow.utils import SkyflowMessages, parse_invoke_connection_response
66
from skyflow.utils.enums import RequestMethod
7+
from skyflow.utils._version import SDK_VERSION
78
from skyflow.vault.connection import InvokeConnectionRequest
89
from skyflow.vault.controller import Connection
910

@@ -21,7 +22,8 @@
2122
INVALID_HEADERS = "invalid_headers"
2223
INVALID_BODY = "invalid_body"
2324
FAILURE_STATUS_CODE = 400
24-
ERROR_RESPONSE_CONTENT = b'{"error": {"message": "Invalid Request"}}'
25+
ERROR_RESPONSE_CONTENT = '"message": "Invalid Request"'
26+
ERROR_FROM_CLIENT_RESPONSE_CONTENT = b'{"error": {"message": "Invalid Request"}}'
2527

2628
class TestConnection(unittest.TestCase):
2729
def setUp(self):
@@ -99,12 +101,14 @@ def test_invoke_request_error(self, mock_send):
99101

100102
with self.assertRaises(SkyflowError) as context:
101103
self.connection.invoke(request)
102-
self.assertEqual(context.exception.message, SkyflowMessages.Error.INVOKE_CONNECTION_FAILED.value)
104+
self.assertEqual(context.exception.message, f'Skyflow Python SDK {SDK_VERSION} Response {ERROR_RESPONSE_CONTENT} is not valid JSON.')
105+
self.assertEqual(context.exception.message, SkyflowMessages.Error.RESPONSE_NOT_JSON.value.format(ERROR_RESPONSE_CONTENT))
106+
self.assertEqual(context.exception.http_code, 400)
103107

104108
def test_parse_invoke_connection_response_error_from_client(self):
105109
mock_response = Mock(spec=requests.Response)
106110
mock_response.status_code = FAILURE_STATUS_CODE
107-
mock_response.content = ERROR_RESPONSE_CONTENT
111+
mock_response.content = ERROR_FROM_CLIENT_RESPONSE_CONTENT
108112
mock_response.headers = {
109113
'error-from-client': 'true',
110114
'x-request-id': '12345'
@@ -117,4 +121,5 @@ def test_parse_invoke_connection_response_error_from_client(self):
117121
exception = context.exception
118122

119123
self.assertTrue(any(detail.get('error_from_client') == 'true' for detail in exception.details))
124+
self.assertEqual(exception.request_id, '12345')
120125

0 commit comments

Comments
 (0)