Problem/Motivation

JSerror doesn't work on any supported version of Drupal.

The 8.x-1.x branch was never actually ported. It sits on the same commit as 7.x-1.x (f860d62) and the code in it is still Drupal 7. jserror.info says core = 7.x, and the module uses .tpl.php templates, hook_menu(), l(), format_date(), format_interval() and truncate_utf8(). All of those went away in Drupal 8.

You can't install it on Drupal 11. Drupal doesn't even see the module, because there is no jserror.info.yml. Running PHPStan over it produces 84 errors, nearly all of them calls to functions that no longer exist.

I'm reviving the module. The branch name is part of the problem here: anyone who finds the project assumes a Drupal 8 version exists when it doesn't.

Steps to reproduce

  1. Install Drupal 11.
  2. Clone the module into web/modules/contrib/jserror and check out 8.x-1.x.
  3. Run drush en jserror.

You get Unable to install modules jserror due to missing modules jserror.

Proposed resolution

Rewrite for Drupal 11 on a 1.0.x branch, keeping the part of the module that's actually worth keeping: a small inline script in the head that installs an error handler before any other script runs, buffers whatever it catches, and only fetches the reporting script once the page has loaded. That's what lets it catch errors thrown while the site's own JavaScript is still loading, which is when the interesting breakage tends to happen.

Structure

  • Routing and controllers instead of hook_menu() and page callbacks.
  • ConfigFormBase and a jserror.settings config object instead of variable_get().
  • Twig templates instead of .tpl.php.
  • Two services, JserrorStorage and UserAgentParser, holding the query and parsing logic.
  • Unit, Kernel and Functional tests.

Behaviour

  • Browscap is no longer a dependency. It ships a large data file that needs regular updates, which is a lot to ask for browser name, major version and OS. There's a small parser in the module now.
  • Unhandled promise rejections are captured too. window.onerror never sees those.
  • Sampling is decided in the browser rather than on the server. A server-side decision gets baked into the page cache and served to everyone, so the percentage you configure wouldn't mean much on a cached site.
  • Report filters live in the query string instead of $_SESSION, so a filtered report is a link you can paste into an issue.
  • New administer jserror permission for the settings form and for clearing the log. Viewing the report still uses access site reports.

Schema fixes

  • line and col were TINYINT, so anything past line 255 was destroyed on the way in. Most errors in bundled JavaScript are past line 255. They're plain integers now.
  • browser_version and platform_version were integers and couldn't hold a value like 10.15.7. They're strings now.

Reporting endpoint

The /jserror endpoint accepts anonymous writes, which is the whole point of it, so it needed tightening:

  • It now requires a JSON content type and a same origin Origin header. Form-encoded, text/plain and multipart POSTs are CORS simple requests, so any site could have made its visitors post here with no preflight and no consent. Those were accepted before.
  • Flood control counts stored rows instead of requests. One request can carry fifty errors, so counting requests understated the real number by a factor of fifty. Rejected submissions cost one unit as well, otherwise sending junk is free.
  • Each field has a byte budget applied before storage. The page URL is copied into every row of a batch, so a generous limit gets multiplied by the batch size.
  • Integers are clamped to the column range and the language value is stripped to ASCII, so a submission can't fail an insert and hand back a 500.
  • The response reports how much of the batch was accepted, so the client re-sends the remainder instead of assuming it all landed.

Report screens

  • Page URLs only become links when they use http or https. Anything else is printed as text, so a stored javascript: URL can't be clicked on a page only admins can reach.
  • Grouped errors are described using a real occurrence. Aggregating each column on its own produced browser and platform combinations that never actually happened together.
  • The summary on the detail page reads a bounded sample of occurrences rather than only the current pager page.

Remaining tasks

  • Rewrite (done)
  • Unit, Kernel and Functional tests (done)
  • PHPCS, PHPStan, ESLint and Stylelint passing (done)
  • GitLab CI (done)
  • Review
  • Tag 1.0.0-alpha1
  • Retire the 8.x-1.x branch
  • Update the project page, it still lists Browscap as a requirement

User interface changes

  • Settings are at /admin/config/development/jserror, with rewritten labels and descriptions.
  • The report at /admin/reports/jserror looks different, filtering happens through the query string, and clearing the log goes through a confirm form.
  • New permission: Administer JSerror.

API changes

All of it. Nothing from 7.x-1.x survives: no function, hook, template or theme function.

The reporting endpoint kept its field names (m, f, l, c, s, w) but takes a JSON body now instead of a form-encoded payload= parameter. Responses include accepted and stored counts.

Data model changes

The jserror table keeps its name and its column names. The types changed as described above. Settings moved from variable_get() to the jserror.settings config object.

There is no upgrade path from 7.x-1.x. No migration, and hook_update_N() doesn't apply because there was never a Drupal 8 or later release to update from. Treat any old error rows as throwaway.

Comments

abhishek-anand created an issue. See original summary.

  • abhishek-anand committed bac93b20 on 1.0.x
    Issue #3613845 by abhishek-anand: Fix GitLab CI pipeline set-up
    
    The...
abhishek-anand’s picture

Issue summary: View changes

  • abhishek-anand committed ebf4a2b9 on 1.0.x
    Issue #3613845 by abhishek-anand: Fix ESLint and CSpell CI failures...

  • abhishek-anand committed 96d3d7e9 on 1.0.x
    Issue #3613845 by abhishek-anand: Port JSerror to Drupal 11
    
    The 8.x-1.x...
abhishek-anand’s picture

Version: 7.x-1.1 » 1.0.x-dev
Status: Active » Fixed

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.

abhishek-anand’s picture

Status: Fixed » Closed (fixed)