33
44#include " core/providers/openvino/ov_interface.h"
55
6+ #include < charconv>
67#include < format>
8+ #include < regex>
79
810#define ORT_API_MANUAL_INIT
911#include " core/session/onnxruntime_cxx_api.h"
1618namespace onnxruntime {
1719namespace openvino_ep {
1820
21+ namespace {
22+ // Helper to extract Level Zero error codes from NPU driver exceptions
23+ struct ZEErrorInfo {
24+ uint32_t code{0 };
25+ std::string name{" UNKNOWN_NPU_ERROR" };
26+
27+ static ZEErrorInfo ExtractFromMessage (std::string_view ov_exception_msg) {
28+ ZEErrorInfo info;
29+
30+ // Extract hex error code: "code 0x([0-9a-fA-F]+)"
31+ std::regex code_pattern (" code 0x([0-9a-fA-F]+)" );
32+ std::string msg_str (ov_exception_msg);
33+ std::smatch matches;
34+ if (std::regex_search (msg_str, matches, code_pattern) && matches.size () > 1 ) {
35+ const auto & code_str = matches[1 ].str ();
36+ std::from_chars (code_str.data (), code_str.data () + code_str.size (), info.code , 16 );
37+ }
38+
39+ // Extract ZE error name: R"(\bZE_\w*\b)"
40+ std::regex name_pattern (R"( \bZE_\w*\b)" );
41+ if (std::regex_search (msg_str, matches, name_pattern)) {
42+ info.name = matches[0 ];
43+ }
44+
45+ return info;
46+ }
47+
48+ // Check if this is ZE_RESULT_ERROR_INVALID_NATIVE_BINARY (driver/binary mismatch)
49+ bool IsInvalidNativeBinary () const {
50+ return code == 0x7800000f ;
51+ }
52+ };
53+ } // namespace
54+
1955template <typename Func, typename ... Args>
2056inline auto OvExceptionBoundary (Func&& func, std::format_string<Args...>&& fmt, Args&&... args) {
2157 return OvExceptionBoundary (func, ORT_EP_FAIL, std::forward<std::format_string<Args...>>(fmt), std::forward<Args>(args)...);
@@ -26,9 +62,25 @@ inline auto OvExceptionBoundary(Func&& func, OrtErrorCode error_code, std::forma
2662 try {
2763 return func ();
2864 } catch (const ov::Exception& e) {
65+ std::string ov_msg = e.what ();
66+
67+ // For import failures, extract and report ZE error codes for better NPU diagnostics
68+ if (error_code == ORT_INVALID_GRAPH) {
69+ auto ze_info = ZEErrorInfo::ExtractFromMessage (ov_msg);
70+ if (ze_info.IsInvalidNativeBinary ()) {
71+ // Enhance message for binary incompatibility (most common import failure)
72+ ov_msg = std::format (" {}, code 0x{:x}\n Model needs to be recompiled\n " ,
73+ ze_info.name , ze_info.code );
74+ } else if (ze_info.code != 0 ) {
75+ // Include ZE error details for other NPU failures
76+ ov_msg = std::format (" {}, code 0x{:x}: {}" ,
77+ ze_info.name , ze_info.code , ov_msg);
78+ }
79+ }
80+
2981 // Encode error code as prefix: "<code>|message"
3082 auto msg = std::format (" {}|{}{}: {}" , static_cast <int >(error_code), log_tag,
31- std::vformat (fmt.get (), std::make_format_args (args...)), e. what () );
83+ std::vformat (fmt.get (), std::make_format_args (args...)), ov_msg );
3284 ORT_THROW (msg);
3385 } catch (...) {
3486 // Encode error code as prefix: "<code>|message"
0 commit comments