The curious case of [nuxt error] Reference Error: geoip2 is not defined

Let’s set the scene…

Dominic PrawnStar Bauer
Nona Digital
Published in
4 min readNov 29, 2019

--

Head of marketing is experiencing a bug. No one else in our office can reproduce the error. WHAT IS GOING ON!?

All we know is that the page isn’t loading correctly, pictures are broken almost everywhere— it’s absolute chaos. Also it’s occurring sporadically, on a small amount of distinctly different devices and browsers.

Image result for no one can reproduce the bug developer meme
If only this meant it always worked :(

We use CloudFront as our CDN. We figured since the images weren’t loading it may mean that the images were incorrectly cached at the edge location? As I said in a previous post — “9/10 times CloudFront is NOT the problem.”

This newly found wisdom would have served us well in this case. We emailed AWS hoping for them to shed light on our issue. All we ended up with was time wasted chasing ghosts and no closer to figuring out WHAT THE HECK IS HAPPENING!? — in short CloudFront was not the issue.

The next important bits of information:

  • Nuxt is used to server side render (SSR) our app.
  • Vue is our frontend framework. (Nuxt should have given this away :P)
  • We were no closer to finding the issue

BUT the universe is kind. Our COO happened to stumble upon the exact same issue — using Brave browser (yeah I’d never heard of it too), a privacy first browser (really worth checking out) that blocks scripts and tracking so that you can stay anonymous while browsing.

It enlightened us to the fact that one of our scripts was being blocked. Which also gave us the following error:

[nuxt] Error while mounting app: ReferenceError: geoip2 is not defined

Hallelujah — finally something to go on.

Doing a quick search through the codebase lead to the following two places of geoip2:

  1. As a script in the head of of our nuxt.config.js
script: 
{
src: 'https://js.maxmind.com/js/apis/geoip2/v2.1/geoip2.js',
async: 'async'
}

2. In our plugins folder for Nuxt we had a plugin called usergeoip.js

const userGeoIP = ({ app: { store } }) => let userCurrencyCookie = getCookie('userCurrency')
let localeCookie = getCookie('locale')
if (userCurrencyCookie === null || localeCookie === null)
{
geoip2.country(geoipOnSuccess, geoipOnError)
}
else ...

The above is just a part of the function as the rest is unimportant. Point 2 is where the geoip2 reference error originated from.

To cut a long debugging story short we uncovered that geoip2 isn’t defined in usergeoip.js when the script (shown above in 1) is blocked. Which makes sense since a reference error indicates that a variable hasn’t been declared.

Another important thing to mention is that other Nuxt plugins won’t load if a Nuxt plugin fails (if you don’t have fallbacks).

We realized that the geoip2 throwing an error on mount had a cascading effect on the rest of the plugins — they didn’t run. One of them was lazy loading which explained why the images were ‘broken’.

Okay great, so the solution should be as simple as adding a conditional to check if geoip2 is undefined right? Something like the following:

if (geoip2 && (userCurrencyCookie === null || localeCookie === null)) 

As with all things I’ve come to realize in programming — IT’S NEVER THAT EASY (well, not often to be more precise).The error persisted.

We were sooooo close WTAF (yeah there’s an A, now you know it’s serious).

To cut another googling/debugging story short the answer lies in the fact that

if (geoip2)

will still throw a reference error if geoip2 is an undeclared variable. The only way to add a conditional that works is:

if (typeof geoip2 === 'undefined')

You need to use typeof as it doesn’t throw a reference error even when geoip2 hasn’t even been declared as a variable — CASE SOLVED!

LESSONS LEARNED:

  1. It’s probably not CloudFront
  2. If you are experiencing sporadic issues amongst varying devices and browsers it’s worthwhile checking the scripts that are being loaded or not being loaded
  3. Check out Brave browser for an easy way to do this
  4. A normal conditional checking if a variable exists doesn’t work on reference errors, you need to use typeof
  5. Nuxt plugins get bottlenecked on mount if a plugin doesn’t load properly be very aware of this. Make sure to have try catches or something else in place to deal with this.
  6. Here’s another cool little typeof gotcha:

--

--

Dominic PrawnStar Bauer
Nona Digital

Slowly trying to piece the world together one idea at a time :).