Index: trac/htdocs/css/trac.css
===================================================================
--- trac/htdocs/css/trac.css	(revision 6674)
+++ trac/htdocs/css/trac.css	(working copy)
@@ -489,8 +489,10 @@
 #content.error form.newticket { display: inline; }
 #content.error form.newticket textarea { display: none; }
 
-#content.error #systeminfo { margin: 1em; width: auto; }
-#content.error #systeminfo th { font-weight: bold; text-align: right; }
+#content.error #systeminfo,
+#content.error #plugins { margin: 1em; width: auto; }
+#content.error #systeminfo th,
+#content.error #plugins th { font-weight: bold; text-align: right; }
 
 #content.error #traceback { margin-left: 1em; }
 #content.error #traceback :link, #content.error #traceback :visited {
@@ -504,7 +506,9 @@
   font-style: normal;
   font-weight: bold;
 }
-#content.error #traceback span.file { color: #666; font-size: 85%; }
+#content.error #traceback span.file,
+#content.error #plugins span.file { color: #666; font-size: 85%; }
+
 #content.error #traceback ul { list-style: none; margin: .5em 0; padding: 0; }
 #content.error #traceback ol {
   border: 1px dotted #d7d7d7;
Index: trac/admin/web_ui.py
===================================================================
--- trac/admin/web_ui.py	(revision 6674)
+++ trac/admin/web_ui.py	(working copy)
@@ -467,7 +467,7 @@
         if changes:
             self.config.save()
 
-    def _render_view(self, req):
+    def get_plugins_data(self):
         plugins = {}
         plugins_dir = os.path.realpath(os.path.join(self.env.path, 'plugins'))
         plugins_dir = os.path.normcase(plugins_dir) # needs to match loader.py
@@ -490,19 +490,25 @@
                 if plugin_filename and os.access(dist.location,
                                                  os.F_OK + os.W_OK):
                     readonly = False
-                if plugin_filename:
+                # retrieve plugin metadata
+                info = get_pkginfo(dist)
+                if not info:
                     info = {'summary': description}
-                    for k in 'author author_email home_page license'.split():
+                    for k in ('author author_email home_page url license trac'
+                              .split()):
                         v = getattr(module, k, '')
                         if v:
+                            if k == 'home_page' or k == 'url':
+                                k = 'home_page'
+                                v = v.replace('$', '').replace('URL: ', '') 
                             info[k] = v
+                # retrieve plugin version info
+                version = dist.version
+                if not version:
                     version = (getattr(module, 'version', '') or
                                getattr(module, 'revision', ''))
                     # special handling for "$Rev$" strings
                     version = version.replace('$', '').replace('Rev: ', 'r') 
-                else:
-                    info = get_pkginfo(dist)
-                    version = dist.version
                 plugins[dist.project_name] = {
                     'name': dist.project_name, 'version': version,
                     'path': dist.location, 'description': description,
@@ -531,12 +537,14 @@
         addons.sort()
         plugin_list += [plugins[category] for category in addons]
 
-        data = {
+        return {
             'plugins': plugin_list,
             'readonly': not os.access(plugins_dir, os.F_OK + os.W_OK)
         }
-        return 'admin_plugins.html', data
 
+    def _render_view(self, req):
+        return 'admin_plugins.html', self.get_plugins_data()
+
     def _find_distribution(self, module):
         path = get_module_path(module)
         if path == self.trac_path:
Index: trac/templates/error.html
===================================================================
--- trac/templates/error.html	(revision 6675)
+++ trac/templates/error.html	(working copy)
@@ -42,7 +42,7 @@
        descr = descr.replace(/==== System Information ====\s+/m,
          "User Agent was: `" + navigator.userAgent + "`\n\n$&"
        );
-       descr = descr.replace(/\|\|\s+==== Python Traceback ====/m,
+       descr = descr.replace(/\|\|\s+==== Enabled Plugins ====/m,
          "||\n|| '''jQuery:''' || `" + $().jquery + "` $&"
        );
        $("#description").text(descr);
@@ -75,6 +75,12 @@
 <py:for each="k, v in trac.systeminfo">
 || '''$k''' || ${'`%s`' % (v and v.replace('\n', '` [[br]] `'))} ||</py:for>
 
+<py:if test="plugins_list">
+==== Enabled Plugins ====
+<py:for each="plugin in plugins_list">
+|| '''`$plugin.name`''' || `$plugin.version` || ${('frame_idx' in plugin and "'''`%s`'''" or "`%s`") % plugin.path} ||</py:for>
+</py:if>
+
 ==== Python Traceback ====
 {{{
 ${traceback}
@@ -121,20 +127,33 @@
               </p>
             </py:when>
             <py:otherwise>
-              <p>If you think this should work you can reproduce the problem,
-              you should consider reporting this to the Trac team.</p>
+              <p>If you think this should work and you can reproduce the problem,
+              you should consider creating a bug report.</p>
+              <py:with vars="faulty_plugins = [p for p in plugins_list if 'frame_idx' in p]">
+                <p py:if="faulty_plugins" py:choose="len(faulty_plugins)">
+                  <py:when test="1">
+                    Note that the ${faulty_plugins[0].name} plugin seems to be involved in this problem. 
+                  </py:when>
+                  <py:otherwise>
+                    Note that the following plugins seem to be involved in this problem: 
+                    ${', '.join([p.name for p in faulty_plugins])}.
+                  </py:otherwise>
+                  <br />
+                  <strong>Please report this issue to the ${tracker.name} plugin maintainer.</strong>
+                </p>
+              </py:with>
               <p>Before you do that, though, please first try
                 <a py:with="q = quote_plus(message[:80])"
-                   href="${trac.homepage}/search?ticket=yes&amp;noquickjump=1&amp;q=$q">searching</a>
+                   href='${tracker.url}/search?ticket=yes&amp;noquickjump=1&amp;q="$q"'>searching</a>
                 for similar issues, as it is quite likely that this problem
                 has been reported before. For questions about installation
-                and configuration of Trac, please try the
+                and configuration of Trac or its plugins, please try the
                 <a href="${trac.homepage}/wiki/MailingList">mailing list</a>
-                instead of filing a ticket.
+                instead of creating a ticket.
               </p>
-              <form class="newticket" method="get" action="${trac.homepage}/newticket">
-                <p>Otherwise, please ${create_ticket(True)} a new ticket at
-                the Trac project site, where you can describe the problem and
+              <form class="newticket" method="get" action="${tracker.url}/newticket">
+                <p>Otherwise, please ${create_ticket(teo=tracker.url=='http://trac.egdewall.org')} a new bug report at
+                the ${tracker.name}'s Trac, where you can describe the problem and
                 explain how to reproduce it.</p>
               </form>
               <py:if test="traceback">
@@ -184,6 +203,23 @@
                   <td>$value</td>
                 </tr>
               </table>
+              <py:if test="plugins_list">
+                <h2>Enabled Plugins</h2>
+                <table class="listing" id="plugins">
+                  <tr py:for="plugin in plugins_list">
+                    <th py:with="url = plugin.info.home_page;
+                                 email = plugin.info.author_email;
+                                 report_url = url or email and 'mailto:'+email">
+                        <a py:strip="not report_url" href="$report_url">$plugin.name</a>
+                    </th>
+                    <td>$plugin.version</td>
+                    <td>
+                      <span class="file"><a py:strip="not plugin.frame_idx" href="#frame$plugin.frame_idx">$plugin.path</a></span>
+                    </td>
+                  </tr>
+                </table>
+              </py:if>
+
             </py:otherwise>
           </py:choose>
         </py:when>
Index: trac/web/main.py
===================================================================
--- trac/web/main.py	(revision 6674)
+++ trac/web/main.py	(working copy)
@@ -39,7 +39,7 @@
 from trac.perm import PermissionCache, PermissionError, PermissionSystem
 from trac.resource import ResourceNotFound
 from trac.util import get_lines_from_file, get_last_traceback, hex_entropy
-from trac.util.compat import partial, reversed
+from trac.util.compat import partial, reversed, any
 from trac.util.datefmt import format_datetime, http_date, localtz, timezone
 from trac.util.text import shorten_line, to_unicode
 from trac.web.api import *
@@ -446,6 +446,7 @@
             message = "%s: %s" % (e.__class__.__name__, to_unicode(e))
             traceback = get_last_traceback()
 
+            # gather frame information
             frames = []
             has_admin = False
             try:
@@ -471,10 +472,59 @@
                                     'vars': tb.tb_frame.f_locals}]
                     tb = tb.tb_next
 
+            # gather plugins information
+            from trac.admin.web_ui import PluginAdminPanel
+            plugins_data = PluginAdminPanel(env).get_plugins_data()
+            # plugins: only keep those which have at least one component enabled
+            plugins_list = [p for p in plugins_data['plugins'][1:]
+                            if any([c['enabled'] for c in p['components']])]
+            # plugins: verify if one of their source file is in the backtrace
+            egg_frames = [(i, f) for i, f in enumerate(frames) 
+                          if f['filename'].startswith('build')]
+            for plugin in plugins_list:
+                plugin_base, ext = os.path.splitext(plugin['path'])
+                if ext == '.egg' and egg_frames:
+                    try:
+                        for dist in pkg_resources.find_distributions(
+                                plugin['path'], only=True):
+                            sources = dist.get_metadata("SOURCES.txt")
+                            for src in sources.splitlines():
+                                if src.endswith('.py'):
+                                    nsrc = os.path.normpath(src)
+                                    for i, f in egg_frames:
+                                        if f['filename'].endswith(nsrc):
+                                            plugin['frame_idx'] = i
+                                            raise StopIteration
+                    except StopIteration:
+                        pass
+                else:
+                    for i, f in enumerate(frames):
+                        if f['filename'].startswith(plugin_base):
+                            plugin['frame_idx'] = i
+                            break
+            # identify tracker in which the bug should be reported
+            teo = 'http://trac.edgewall.org'
+            th = 'http://trac-hacks.org'
+            tracker_name = 'Trac project'
+            tracker_url = teo
+            topmost = 0
+            for plugin in plugins_list:
+                if 'frame_idx' in plugin:
+                    i = plugin['frame_idx']
+                    if i > topmost:
+                        topmost = i
+                        tracker_name = plugin['name']
+                        if 'trac' in plugin['info']:
+                            tracker_url = plugin['info']['trac']
+                        elif plugin['info'].get('home_page', '').startswith(th):
+                            tracker_url = th
+
             data = {'title': 'Internal Error',
                     'type': 'internal', 'message': message,
                     'traceback': traceback, 'frames': frames,
-                    'shorten_line': shorten_line}
+                    'shorten_line': shorten_line, 
+                    'plugins_list': plugins_list, 
+                    'tracker': {'name': tracker_name, 'url': tracker_url}}
 
             try:
                 req.send_error(exc_info, status=500, env=env, data=data)

