diff --git a/api/src/backend/api/attack_paths/sink/neptune.py b/api/src/backend/api/attack_paths/sink/neptune.py index dbb687e89c..c68b6f8277 100644 --- a/api/src/backend/api/attack_paths/sink/neptune.py +++ b/api/src/backend/api/attack_paths/sink/neptune.py @@ -66,7 +66,7 @@ READ_EXCEPTION_CODES = [ "Neo.ClientError.Procedure.ProcedureNotFound", ] CLIENT_STATEMENT_EXCEPTION_PREFIX = "Neo.ClientError.Statement." -RETRYABLE_WRITE_ERROR_PREFIXES = ( +RETRYABLE_WRITE_ERROR_FRAGMENTS = ( "Operation failed due to conflicting concurrent operations", "Operation terminated (deadline exceeded)", ) @@ -78,7 +78,8 @@ SIGV4_TOKEN_LIFETIME_MINUTES = 4 def _is_retryable_write_error(exc: Exception) -> bool: if not isinstance(exc, neo4j.exceptions.Neo4jError): return False - return bool(exc.message and exc.message.startswith(RETRYABLE_WRITE_ERROR_PREFIXES)) + message = exc.message or "" + return any(fragment in message for fragment in RETRYABLE_WRITE_ERROR_FRAGMENTS) class NeptuneSink(SinkDatabase): diff --git a/api/src/backend/api/tests/test_sink.py b/api/src/backend/api/tests/test_sink.py index 3636771ddc..487519923e 100644 --- a/api/src/backend/api/tests/test_sink.py +++ b/api/src/backend/api/tests/test_sink.py @@ -332,9 +332,10 @@ class TestNeptuneRetryPolicy: @pytest.mark.parametrize( "message", [ - "Operation failed due to conflicting concurrent operations " - + "(please retry), 0 transactions are currently rolling back.", - "Operation terminated (deadline exceeded)", + "Unexpected server exception 'Operation failed due to conflicting " + "concurrent operations (please retry), 0 transactions are currently " + "rolling back.'", + "Unexpected server exception 'Operation terminated (deadline exceeded)'", ], ) def test_observed_transient_write_errors_are_retryable(self, message): @@ -345,7 +346,9 @@ class TestNeptuneRetryPolicy: def test_unrelated_database_error_is_not_retryable(self): error = MagicMock(spec=neo4j.exceptions.Neo4jError) - error.message = "Operation terminated (out of memory)" + error.message = ( + "Unexpected server exception 'Operation terminated (out of memory)'" + ) assert _is_retryable_write_error(error) is False