DEV Community

Cover image for Why the OpenTelemetry browser SDK wouldn't start on Safari 17
Aditya Reddy
Aditya Reddy

Posted on AI-assisted

Why the OpenTelemetry browser SDK wouldn't start on Safari 17

On September 30 someone filed an issue on the OpenTelemetry browser SDK. startBrowserSdk was throwing TypeError: URL.parse is not a function on older browsers, so the SDK never started there at all.

Nothing caught the error, so an app that started the SDK on load (the issue's example was while rendering a React provider) went down with it. Blank page, in production builds. The issue came with a clean reproduction too (Chromium 125 failed, Chromium 127 started fine), which made it easy to pick up.

I went looking and it was one line. The SDK checks the export URL every time it starts, and it did that with URL.parse:

const parsed = URL.parse(url);
Enter fullscreen mode Exit fullscreen mode

Problem is, URL.parse is new. Safari only got it in version 18, Chrome and Firefox in 126, all in 2024. Anyone on Safari 17, which includes iPhones still on iOS 17, or on a Chrome or Firefox older than 126 doesn't have it. The older way, new URL(url), has worked everywhere for years. It throws on a bad URL instead of returning null though, which is a big part of why URL.parse was added in the first place.

So the fix goes back to the try/catch:

let parsed: URL | null;
try {
  // Not `URL.parse`, which Safari < 18 and Chrome/Firefox < 126 lack.
  parsed = new URL(url);
} catch {
  parsed = null;
}
Enter fullscreen mode Exit fullscreen mode

A URL that doesn't parse, or isn't http or https, still returns null and logs an error like before, and the SDK still refuses to start on it. Other parts of the repo already parsed URLs this way, so it wasn't a new pattern for anyone reviewing it.

Testing was the annoying part, cause I didn't have an old Safari lying around. What I did instead was delete URL.parse in current Chrome and start the SDK:

const urlParse = Object.getOwnPropertyDescriptor(URL, 'parse');
Reflect.deleteProperty(URL, 'parse');

try {
  browserSdk = startBrowserSdk({ /* short batch delay for the test */ });
  // emit a log and a span, then wait for the export
} finally {
  if (urlParse) {
    Object.defineProperty(URL, 'parse', urlParse);
  }
}
Enter fullscreen mode Exit fullscreen mode

That test failed on main with the exact error from the issue and passed with the fix. I never ran it on a real Safari 17 or Chrome 125, and I said so in the PR.

The bit I keep thinking about is why lint didn't catch it. The repo runs eslint-plugin-baseline-js set to available: 'widely', which is there to stop exactly this kind of thing. It let URL.parse through cause its data counts URL.parse as part of the older url feature, and that one has been widely available for a long time. So a method Safari has had for about two years passed the check. I left the lint config alone, it felt like its own conversation.

David Luna merged it on October 2.

PR: https://github.com/open-telemetry/opentelemetry-browser/pull/447
Issue: https://github.com/open-telemetry/opentelemetry-browser/issues/445

Top comments (0)