changeset 765:3d266adce4b9

added debug info when throwing internal exceptions
author Alain Mazy <am@orthanc.team>
date Wed, 17 Jun 2026 16:25:05 +0200
parents 25d0de65d2a8
children b2d7a0d9bd62
files Plugin/Configuration.cpp Plugin/DicomWebClient.cpp Plugin/DicomWebFormatter.cpp Plugin/DicomWebServers.cpp Plugin/Plugin.cpp Plugin/QidoRs.cpp Plugin/StowRs.cpp Plugin/WadoRs.cpp Plugin/WadoRsRetrieveFrames.cpp Plugin/WadoRsRetrieveRendered.cpp Plugin/WadoUri.cpp Resources/Orthanc/Plugins/OrthancPluginException.h
diffstat 12 files changed, 68 insertions(+), 52 deletions(-) [+]
line wrap: on
line diff
--- a/Plugin/Configuration.cpp	Wed Jun 17 10:42:25 2026 +0200
+++ b/Plugin/Configuration.cpp	Wed Jun 17 16:25:05 2026 +0200
@@ -194,7 +194,9 @@
   {
     if (json.type() != Json::objectValue)
     {
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat);
+      throw Orthanc::OrthancException(
+        Orthanc::ErrorCode_BadFileFormat,
+        "The field \"" + key + "\" must be a JSON object");
     }
     else if (!json.isMember(key))
     {
@@ -220,7 +222,7 @@
   {
     if (json.type() != Json::objectValue)
     {
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat);
+      PLUGIN_THROW_WITH_FILE_AND_LINE_INFO(Orthanc::ErrorCode_BadFileFormat);
     }
     else if (!json.isMember(key))
     {
@@ -229,7 +231,7 @@
     else if (json[key].type() != Json::intValue &&
              json[key].type() != Json::uintValue)
     {
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat);      
+      PLUGIN_THROW_WITH_FILE_AND_LINE_INFO(Orthanc::ErrorCode_BadFileFormat);      
     }
     else
     {
@@ -245,7 +247,7 @@
   {
     if (json.type() != Json::objectValue)
     {
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat);
+      PLUGIN_THROW_WITH_FILE_AND_LINE_INFO(Orthanc::ErrorCode_BadFileFormat);
     }
     else if (!json.isMember(key))
     {
@@ -253,7 +255,7 @@
     }
     else if (json[key].type() != Json::booleanValue)
     {
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat);      
+      PLUGIN_THROW_WITH_FILE_AND_LINE_INFO(Orthanc::ErrorCode_BadFileFormat);      
     }
     else
     {
@@ -720,7 +722,7 @@
           break;
 
         default:
-          throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
+          PLUGIN_THROW_WITH_FILE_AND_LINE_INFO(Orthanc::ErrorCode_ParameterOutOfRange);
       }
 
       std::string value = GetStringValue(key, FULL);
@@ -787,7 +789,7 @@
           break;
 
         default:
-          throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
+          PLUGIN_THROW_WITH_FILE_AND_LINE_INFO(Orthanc::ErrorCode_ParameterOutOfRange);
       }
     }
 
--- a/Plugin/DicomWebClient.cpp	Wed Jun 17 10:42:25 2026 +0200
+++ b/Plugin/DicomWebClient.cpp	Wed Jun 17 16:25:05 2026 +0200
@@ -118,7 +118,7 @@
 
     if (factory_ != NULL)
     {
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
+      PLUGIN_THROW_WITH_FILE_AND_LINE_INFO(Orthanc::ErrorCode_BadSequenceOfCalls);
     }
     else
     {
@@ -281,7 +281,7 @@
   {
     if (factory_ == NULL)
     {
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
+      PLUGIN_THROW_WITH_FILE_AND_LINE_INFO(Orthanc::ErrorCode_BadSequenceOfCalls);
     }
 
     FunctionResult result;
@@ -307,7 +307,7 @@
         return OrthancPluginJobStepStatus_Failure;
 
       default:
-        throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
+        PLUGIN_THROW_WITH_FILE_AND_LINE_INFO(Orthanc::ErrorCode_InternalError);
     }
   }
 
@@ -526,7 +526,7 @@
   {
     if (resources[i].type() != Json::stringValue)
     {
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat);
+      PLUGIN_THROW_WITH_FILE_AND_LINE_INFO(Orthanc::ErrorCode_BadFileFormat);
     }
 
     std::string resource = resources[i].asString();
@@ -553,7 +553,7 @@
     {
       if (tmpInstances.type() != Json::arrayValue)
       {
-        throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
+        PLUGIN_THROW_WITH_FILE_AND_LINE_INFO(Orthanc::ErrorCode_InternalError);
       }
 
       AddResourceForJobContent(resourcesForJobContent, Orthanc::StringToResourceType(tmpResource["Type"].asString().c_str()), resource);
@@ -1068,7 +1068,7 @@
     }
     else
     {
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);      
+      PLUGIN_THROW_WITH_FILE_AND_LINE_INFO(Orthanc::ErrorCode_InternalError);      
     }
 
     if (debug_)
@@ -1116,7 +1116,7 @@
     }
     else if (state_ != State_Headers)
     {
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
+      PLUGIN_THROW_WITH_FILE_AND_LINE_INFO(Orthanc::ErrorCode_InternalError);
     }
 
     if (boost::iequals(key, "Content-Type"))
@@ -1299,7 +1299,7 @@
       const Resource* resource = resources_[position_++];
       if (resource == NULL)
       {
-        throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
+        PLUGIN_THROW_WITH_FILE_AND_LINE_INFO(Orthanc::ErrorCode_InternalError);
       }
 
       const std::map<std::string, std::string>& headers = resource->GetAdditionalHeaders();
--- a/Plugin/DicomWebFormatter.cpp	Wed Jun 17 10:42:25 2026 +0200
+++ b/Plugin/DicomWebFormatter.cpp	Wed Jun 17 16:25:05 2026 +0200
@@ -168,7 +168,7 @@
     if (context_ == NULL ||
         (isXml_ && output_ == NULL))  // allow no output when working with Json output.
     {
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer);
+      PLUGIN_THROW_WITH_FILE_AND_LINE_INFO(Orthanc::ErrorCode_NullPointer);
     }
 
     if (isXml_)
--- a/Plugin/DicomWebServers.cpp	Wed Jun 17 10:42:25 2026 +0200
+++ b/Plugin/DicomWebServers.cpp	Wed Jun 17 16:25:05 2026 +0200
@@ -321,7 +321,7 @@
 
     if (json.type() != Json::objectValue)
     {
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
+      PLUGIN_THROW_WITH_FILE_AND_LINE_INFO(Orthanc::ErrorCode_InternalError);
     }
 
     Json::Value::Members members = json.getMemberNames();
@@ -331,7 +331,7 @@
 
       if (json[key].type() != Json::stringValue)
       {
-        throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
+        PLUGIN_THROW_WITH_FILE_AND_LINE_INFO(Orthanc::ErrorCode_InternalError);
       }
       else
       {
--- a/Plugin/Plugin.cpp	Wed Jun 17 10:42:25 2026 +0200
+++ b/Plugin/Plugin.cpp	Wed Jun 17 16:25:05 2026 +0200
@@ -736,7 +736,7 @@
               root[0] != '/' ||
               root[root.size() - 1] != '/')
           {
-            throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
+            PLUGIN_THROW_WITH_FILE_AND_LINE_INFO(Orthanc::ErrorCode_InternalError);
           }
 
           std::map<std::string, std::string> dictionary;
--- a/Plugin/QidoRs.cpp	Wed Jun 17 10:42:25 2026 +0200
+++ b/Plugin/QidoRs.cpp	Wed Jun 17 16:25:05 2026 +0200
@@ -113,7 +113,7 @@
           break;
 
         default:
-          throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
+          PLUGIN_THROW_WITH_FILE_AND_LINE_INFO(Orthanc::ErrorCode_InternalError);
       }
     }
 
@@ -275,7 +275,7 @@
           break;
 
         default:
-          throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
+          PLUGIN_THROW_WITH_FILE_AND_LINE_INFO(Orthanc::ErrorCode_InternalError);
       }
 
       bool caseSensitive;
@@ -413,7 +413,7 @@
   if (!OrthancPlugins::RestApiPost(resources, "/tools/find", find, httpHeaders, true) ||
       resources.type() != Json::arrayValue)
   {
-    throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
+    PLUGIN_THROW_WITH_FILE_AND_LINE_INFO(Orthanc::ErrorCode_InternalError);
   }
 
   std::string wadoBasePublicUrl = OrthancPlugins::Configuration::GetBasePublicUrl(request);
--- a/Plugin/StowRs.cpp	Wed Jun 17 10:42:25 2026 +0200
+++ b/Plugin/StowRs.cpp	Wed Jun 17 16:25:05 2026 +0200
@@ -300,7 +300,7 @@
   
     if (request->method != OrthancPluginHttpMethod_Post)
     {
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
+      PLUGIN_THROW_WITH_FILE_AND_LINE_INFO(Orthanc::ErrorCode_InternalError);
     }
 
     std::map<std::string, std::string> headers;
--- a/Plugin/WadoRs.cpp	Wed Jun 17 10:42:25 2026 +0200
+++ b/Plugin/WadoRs.cpp	Wed Jun 17 16:25:05 2026 +0200
@@ -118,7 +118,7 @@
       return "/instances/" + publicId;
       
     default:
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
+      PLUGIN_THROW_WITH_FILE_AND_LINE_INFO(Orthanc::ErrorCode_InternalError);
   }
 }
 
@@ -788,7 +788,7 @@
           context, output, reinterpret_cast<const char*>(dicom->GetBuffer()),
           dicom->GetSize()) != 0)
       {
-        throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
+        PLUGIN_THROW_WITH_FILE_AND_LINE_INFO(Orthanc::ErrorCode_InternalError);
       }
       perfTotalSizeInBytes += dicom->GetSize();
 
@@ -969,7 +969,7 @@
       if (value.type() != Json::objectValue ||
           !value.isMember(MAIN_DICOM_TAGS))
       {
-        throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
+        PLUGIN_THROW_WITH_FILE_AND_LINE_INFO(Orthanc::ErrorCode_InternalError);
       }
 
       dicom.FromDicomAsJson(value[MAIN_DICOM_TAGS], false /* append */, true /* parseSequences */);
@@ -982,7 +982,7 @@
         }
         else
         {
-          throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
+          PLUGIN_THROW_WITH_FILE_AND_LINE_INFO(Orthanc::ErrorCode_InternalError);
         }
       }
         
@@ -995,7 +995,7 @@
         }
         else
         {
-          throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
+          PLUGIN_THROW_WITH_FILE_AND_LINE_INFO(Orthanc::ErrorCode_InternalError);
         }
       }
 
@@ -1029,7 +1029,7 @@
               if (!value.isMember(INSTANCES) ||
                   value[INSTANCES].type() != Json::arrayValue)
               {
-                throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
+                PLUGIN_THROW_WITH_FILE_AND_LINE_INFO(Orthanc::ErrorCode_InternalError);
               }
               else
               {
@@ -1037,7 +1037,7 @@
                 {
                   if (value[INSTANCES][i].type() != Json::stringValue)
                   {
-                    throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
+                    PLUGIN_THROW_WITH_FILE_AND_LINE_INFO(Orthanc::ErrorCode_InternalError);
                   }
                   else
                   {
@@ -1055,7 +1055,7 @@
               {
                 if (tmp.type() != Json::arrayValue)
                 {
-                  throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
+                  PLUGIN_THROW_WITH_FILE_AND_LINE_INFO(Orthanc::ErrorCode_InternalError);
                 }
 
                 for (Json::Value::ArrayIndex i = 0; i < tmp.size(); i++)
@@ -1064,7 +1064,7 @@
                       !tmp[i].isMember("ID") ||
                       tmp[i]["ID"].type() != Json::stringValue)
                   {
-                    throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
+                    PLUGIN_THROW_WITH_FILE_AND_LINE_INFO(Orthanc::ErrorCode_InternalError);
                   }
                   else
                   {
@@ -1077,7 +1077,7 @@
             }
 
             default:
-              throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented);
+              PLUGIN_THROW_WITH_FILE_AND_LINE_INFO(Orthanc::ErrorCode_NotImplemented);
           }
 
           
@@ -1235,7 +1235,7 @@
     }
 
     default:
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
+      PLUGIN_THROW_WITH_FILE_AND_LINE_INFO(Orthanc::ErrorCode_InternalError);
   }
     
   
@@ -1344,7 +1344,7 @@
     if (!OrthancPlugins::RestApiPost(resources, "/tools/find", payload, httpHeaders, true) ||
         resources.type() != Json::arrayValue)
     {
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
+      PLUGIN_THROW_WITH_FILE_AND_LINE_INFO(Orthanc::ErrorCode_InternalError);
     }
 
     if (resources.size() == 0)
@@ -1727,7 +1727,7 @@
   {
     if (instancesQueue == NULL)
     {
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer);
+      PLUGIN_THROW_WITH_FILE_AND_LINE_INFO(Orthanc::ErrorCode_NullPointer);
     }
   }
 
@@ -1758,7 +1758,7 @@
       std::unique_ptr<InstanceToLoad> instanceToLoad(data->Dequeue());
       if (instanceToLoad.get() == NULL)
       {
-        throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
+        PLUGIN_THROW_WITH_FILE_AND_LINE_INFO(Orthanc::ErrorCode_InternalError);
       }
 
       if (instanceToLoad->GetOrthancId() == EXIT_WORKER_MESSAGE)
@@ -2208,7 +2208,7 @@
         if (frames.type() != Json::arrayValue ||
             OrthancPluginStartMultipartAnswer(context, output, "related", "application/octet-stream") != 0)
         {
-          throw Orthanc::OrthancException(Orthanc::ErrorCode_Plugin);
+          PLUGIN_THROW_WITH_FILE_AND_LINE_INFO(Orthanc::ErrorCode_Plugin);
         }
 
         for (Json::Value::ArrayIndex i = 0; i < frames.size(); i++)
@@ -2219,7 +2219,7 @@
               !OrthancPlugins::RestApiGetString(frame, orthanc + "/" + frames[i].asString(), false) ||
               OrthancPluginSendMultipartItem(context, output, frame.c_str(), frame.size()) != 0)
           {
-            throw Orthanc::OrthancException(Orthanc::ErrorCode_Plugin);
+            PLUGIN_THROW_WITH_FILE_AND_LINE_INFO(Orthanc::ErrorCode_Plugin);
           }
         }
       }
@@ -2261,7 +2261,7 @@
         if (OrthancPluginStartMultipartAnswer(context, output, "related", "application/octet-stream") != 0 ||
             OrthancPluginSendMultipartItem(context, output, result.c_str(), result.size()) != 0)
         {
-          throw Orthanc::OrthancException(Orthanc::ErrorCode_Plugin);
+          PLUGIN_THROW_WITH_FILE_AND_LINE_INFO(Orthanc::ErrorCode_Plugin);
         }
       }
       else
--- a/Plugin/WadoRsRetrieveFrames.cpp	Wed Jun 17 10:42:25 2026 +0200
+++ b/Plugin/WadoRsRetrieveFrames.cpp	Wed Jun 17 16:25:05 2026 +0200
@@ -594,7 +594,7 @@
 
     if (instance.get() == NULL)
     {
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer);
+      PLUGIN_THROW_WITH_FILE_AND_LINE_INFO(Orthanc::ErrorCode_NullPointer);
     }
 
     if (allFrames)
--- a/Plugin/WadoRsRetrieveRendered.cpp	Wed Jun 17 10:42:25 2026 +0200
+++ b/Plugin/WadoRsRetrieveRendered.cpp	Wed Jun 17 16:25:05 2026 +0200
@@ -688,7 +688,7 @@
         }
 
         default:
-          throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented);
+          PLUGIN_THROW_WITH_FILE_AND_LINE_INFO(Orthanc::ErrorCode_NotImplemented);
       }
 
       Orthanc::ImageTraits<Orthanc::PixelFormat_Grayscale8>::SetFloatPixel(target, b, x, y);
@@ -751,14 +751,14 @@
           break;
 
         default:
-          throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented);
+          PLUGIN_THROW_WITH_FILE_AND_LINE_INFO(Orthanc::ErrorCode_NotImplemented);
       }
           
       break;
     }
 
     default:
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented);
+      PLUGIN_THROW_WITH_FILE_AND_LINE_INFO(Orthanc::ErrorCode_NotImplemented);
   }
 
   if (parameters.IsFlipX())
@@ -1047,7 +1047,7 @@
         break;
 
       default:
-        throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented);
+        PLUGIN_THROW_WITH_FILE_AND_LINE_INFO(Orthanc::ErrorCode_NotImplemented);
     }
   }
 }
--- a/Plugin/WadoUri.cpp	Wed Jun 17 10:42:25 2026 +0200
+++ b/Plugin/WadoUri.cpp	Wed Jun 17 16:25:05 2026 +0200
@@ -106,7 +106,7 @@
   if (!OrthancPlugins::RestApiPost(resources, "/tools/find", payload, httpHeaders, true) ||
       resources.type() != Json::arrayValue)
   {
-    throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
+    PLUGIN_THROW_WITH_FILE_AND_LINE_INFO(Orthanc::ErrorCode_InternalError);
   }
 
   if (resources.size() == 0)
@@ -171,7 +171,7 @@
   else
   {
     LOG(ERROR) << "WADO-URI: Unable to generate a preview image for " << uri;
-    throw Orthanc::OrthancException(Orthanc::ErrorCode_Plugin);
+    PLUGIN_THROW_WITH_FILE_AND_LINE_INFO(Orthanc::ErrorCode_Plugin);
   }
 }
 
--- a/Resources/Orthanc/Plugins/OrthancPluginException.h	Wed Jun 17 10:42:25 2026 +0200
+++ b/Resources/Orthanc/Plugins/OrthancPluginException.h	Wed Jun 17 16:25:05 2026 +0200
@@ -40,14 +40,28 @@
 #  define ORTHANC_PLUGINS_GET_ERROR_CODE(code)  ::OrthancPluginErrorCode_ ## code
 #endif
 
+#if HAS_ORTHANC_EXCEPTION == 1 && defined(__ORTHANC_FILE__)   // the OrthancException accepts a detail argument -> add the file and line number
+#  define PLUGIN_ORTHANC_EXCEPTION_STRINGIFY_LINE_HELPER(line) #line
+#  define PLUGIN_ORTHANC_EXCEPTION_STRINGIFY_LINE(line) PLUGIN_ORTHANC_EXCEPTION_STRINGIFY_LINE_HELPER(line)
+#  define PLUGIN_THROW_WITH_FILE_AND_LINE_INFO(errorCode)                    \
+    throw ::Orthanc::OrthancException(                                               \
+      errorCode, #errorCode " triggered from " __ORTHANC_FILE__ ":"       \
+      PLUGIN_ORTHANC_EXCEPTION_STRINGIFY_LINE(__LINE__))
 
-#define ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(code)                   \
-  throw ORTHANC_PLUGINS_EXCEPTION_CLASS(static_cast<ORTHANC_PLUGINS_ERROR_ENUMERATION>(code));
+#  define ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(code)                   \
+  PLUGIN_THROW_WITH_FILE_AND_LINE_INFO(static_cast<ORTHANC_PLUGINS_ERROR_ENUMERATION>(code))    
+
+#  define ORTHANC_PLUGINS_THROW_EXCEPTION(code)                           \
+  PLUGIN_THROW_WITH_FILE_AND_LINE_INFO(ORTHANC_PLUGINS_GET_ERROR_CODE(code))    
+
+#else // the PluginException does not accept a detail argument
+#  define ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(code)                   \
+    throw ORTHANC_PLUGINS_EXCEPTION_CLASS(static_cast<ORTHANC_PLUGINS_ERROR_ENUMERATION>(code));
 
 
-#define ORTHANC_PLUGINS_THROW_EXCEPTION(code)                           \
-  throw ORTHANC_PLUGINS_EXCEPTION_CLASS(ORTHANC_PLUGINS_GET_ERROR_CODE(code));
-                                                  
+#  define ORTHANC_PLUGINS_THROW_EXCEPTION(code)                           \
+    throw ORTHANC_PLUGINS_EXCEPTION_CLASS(ORTHANC_PLUGINS_GET_ERROR_CODE(code));
+#endif                                                  
 
 #define ORTHANC_PLUGINS_CHECK_ERROR(code)                           \
   if (code != ORTHANC_PLUGINS_GET_ERROR_CODE(Success))              \