quick-lint-js

quick-lint-js finds bugs in JavaScript programs.

quick-lint-js can find the following warnings and errors in your code:

E001: variable assigned before its declaration

Variables declared with let can only be reassigned by code below the declaration. The assignment will crash with a ReferenceError if you assign to the variable.

function getNumberOfChocolates() { return 3; }
let shouldEatChocolates = true;

if (shouldEatChocolates) {
  chocolates = 0;
}
let chocolates = getNumberOfChocolates();

To fix this error, move the declaration above the assignment:

function getNumberOfChocolates() { return 3; }
let shouldEatChocolates = true;

let chocolates = getNumberOfChocolates();
if (shouldEatChocolates) {
  chocolates = 0;
}

E002: assignment to const global variable

Infinity, NaN, and undefined are global variables which cannot be changed. Assignments to these variables are silently ignored.

NaN = 0;
undefined = null;

To fix this error, pick a different variable to assign to.

E003: assignment to const variable

You cannot reassign variables declared with const. The assignment will crash with a ReferenceError if you run the code.

const pi = 3.14;
pi = 6;

const friends = ["Alice"];
friends = ["Bob"];

To fix this error, assign to a different variable, declare a new variable with a different name, or change const to let:

let pi = 3.14;
pi = 6;

const friends = ["Alice"];
const acquaintances = ["Bob"];

E004: assignment to const variable before its declaration

You cannot reassign variables declared with const, and you cannot reference a variable declared with const above its declaration. The assignment will crash with a ReferenceError if you run the code.

let timeElapsed = 31;

let pie = "cooking";
if (timeElapsed > 30) {
  pi = "cooked";
}
const pi = 3.14;

To fix this error, assign to a different variable or declare a new variable with a different name:

let timeElapsed = 31;

let pie = "cooking";
if (timeElapsed > 30) {
  pie = "cooked";
}
const pi = 3.14;

See also: E001, E003

E005: BigInt literal contains decimal point

BigInt literals are number literals with an n suffix. These literals must represent integers and cannot contain a decimal point (.).

let gallons = 3.50n;
let pennies = 100.00n;

To fix this error, make the number literal a Number literal by removing the n suffix, or remove the fractional portion of the number:

let gallons = 3.50;
let pennies = 100n;

E006: BigInt literal contains exponent

BigInt literals are number literals with an n suffix. These literals must represent integers and cannot contain exponents (e).

let atomDiameter = 1e-10n;
let score = 1e2n;

To fix this error, make the number literal a Number literal by removing the n suffix, or expand the exponent of the number:

let atomDiameter = 1e-10;
let score = 100n;

E007: classes cannot be named 'let'

Classes declared with class cannot be named let.

class let {
  bark() {
    console.log("woof");
  }
}

To fix this error, name the class something other than let, or declare the class with var:

class Dog {
  bark() {
    console.log("woof");
  }
}

var let = class {
  bark() {
    console.log("woof");
  }
};

E008: let statement cannot declare variables named 'let'

Variables declared with let cannot be named let.

function getLotNumber() { return 42; }

let let = getLotNumber();
console.log(let);

To fix this error, name the variable something other than let, or declare the variable with var:

function getLotNumber() { return 42; }

let lot = getLotNumber();
console.log(lot);

var let = getLotNumber();
console.log(let);

E009: cannot export variable named 'let'

An exported function cannot be named let:

export function let() {
  console.log("access permitted");
}

To fix this error, name the function something other than let, or declare the function separately with a different name and use export-as:

export function allow() {
  console.log("access permitted");
}

function allowAccess() {
  console.log("access permitted");
}
export { allowAccess as let };

E010: cannot import 'let'

An imported function or variable cannot be named let:

import { let } from "./security.mjs";

To fix this error, name the function or variable something other than let, or rename the function or variable using import-as:

import { allow } from "./security.mjs";

import { let as permit } from "./security.mjs";

E012: escaped character is not allowed in identifiers

A function or variable name includes a Unicode escape sequence, and the escape sequence refers to a character which isn't allowed in a function or variable name:

let guitar\u2604 = "\uD83C\uDFB8";
let handc\uffed = true;

To fix this error, use the code point of a Unicode character which is allowed, or remove the extraneous backslash from the name:

let guitar\u3604 = "\uD83C\uDFB8";
let handcuffed = true;

The initial character in a function or variable name can be any of the following:

Characters after the initial character in a function or variable name can be any of the following:

E013: code point out of range

A function or variable name includes a Unicode escape sequence, and the escape sequence refers to a character which is beyond the range of valid Unicode code points (U+0000 to U+10FFFF):

class ChirpSound {}
let bird\u{360000} = new ChirpSound();

To fix this error, use the code point of a Unicode character which is in range:

class ChirpSound {}
let bird\u{3600} = new ChirpSound();

E014: expected expression before newline

throw statements cannot have a newline between the throw keyword and the thrown expression:

throw
  new Error(
    "something terrible happened!"
  );

To fix this error, add parentheses:

throw (
  new Error(
    "something terrible happened!"
  )
);

Alternatively, start the expression on the same line as the throw keyword:

throw new Error(
  "something terrible happened!"
);

E015: expected expression before semicolon

throw statements require an expression following the throw keyword. It is an error to rethrow an exception by writing just throw;:

try {
  goNuts();
} catch (e) {
  console.error(`couldn't handle deez nuts: ${e}`);
  throw;
}

function goNuts() {}

To rethrow an exception, name the exception variable after throw:

try {
  goNuts();
} catch (e) {
  console.error(`couldn't handle deez nuts: ${e}`);
  throw e;
}

function goNuts() {}

E016: expected hexadecimal digits in Unicode escape sequence

In variable names and strings, a Unicode escape sequence must contain only hexadecimal digits (any of 0123456789abcdefABCDEF). It is an error if other characters appear within a Unicode escape sequence:

console.log("List of Pok\ue9mon by weight:");
console.log("Nidoran\u{2642 {male}");

For an escape sequence without { and }, add { and }:

console.log("List of Pok\u{e9}mon by weight:");

Alternatively, for an escape sequence without { and }, include 0 digits such that the escape sequence contains exactly four hexadecimal digits:

console.log("List of Pok\u00e9mon by weight:");

For an escape sequence with { and }, ensure the } appears after the hexadecimal digits:

console.log("Nidoran\u{2642} {male}");

E017: if statement needs parentheses around condition

In JavaScript, if statements require parentheses around the condition. It is an error to omit the parentheses:

if 2 + 2 == 4 {
  console.log("Math works!");
}

To fix this error, add ( and ):

if (2 + 2 == 4) {
  console.log("Math works!");
}

E018: if statement is missing '(' or ')' around condition

An if statement is missing either ( before the condition or ) after the condition:

if (2 + 2 == 4 {
  console.log("Math works!");
}
if 4 == 2 + 2) {
  console.log("Jedi math works!");
}

To fix this error, add the missing ( or ):

if (2 + 2 == 4) {
  console.log("Math works!");
}
if (4 == 2 + 2) {
  console.log("Jedi math works!");
}

E021: invalid lone literal in object literal

An object literal entry must either be a key: value pair, a method, or variable short-hand. It is an error to use the short-hand syntax with anything except a variable name:

// A tasty enum
const FRUITS = {
  "BANANA",
  "ORANGE",
  "STRAWBERRY",
  "KIWI",
};

// Pre-computed for speed
let smallPrimes = {2, 3, 5, 7, 11, 13, 17, 19};

To fix this error, either use the key: value pair syntax, or use [ ] to create an array literal instead of an object literal:

// A tasty enum
const FRUITS = {
  BANANA: "BANANA",
  ORANGE: "ORANGE",
  STRAWBERRY: "STRAWBERRY",
  KIWI: "KIWI",
};

// Pre-computed for speed
let smallPrimes = [2, 3, 5, 7, 11, 13, 17, 19];

E023: keywords cannot contain escape sequences

Outside a string or template literal, Unicode escape sequences (like \u{65}) can be used in identifiers. However, Unicode escape sequences are not allowed if they would make an identifier look like a keyword when unescaped:

let \u{69}\u{66} = "if";
let which = \u{66}inally;

To fix this error, either pick a different variable name, or make a string:

let _\u{69}\u{66} = "if";
let which = "\u{66}inally";

E024: const/let/var with no bindings

const, let, or var statements need to declare at least one variable. It is an error to declare nothing:

var
const friends = ["strager"];
for (let  of friends) {
}

To fix this error, add a variable name:

var bestFriend;
const friends = ["strager"];
for (let friend of friends) {
  bestFriend = friend;
}

E025: missing comma between object literal entries

Object literal entries, including methods, are separated by commas. It is an error to write two entries without a comma in between:

const snuffles = {
  age: 7
  meow() {
    console.log("😾")
  }
  eat() {
    console.log("😸")
  }
}

To fix this error, include commas:

const snuffles = {
  age: 7,
  meow() {
    console.log("😾")
  },
  eat() {
    console.log("😸")
  }
}

E026: missing operand for operator

Binary operators (such as * and >>) require an expression (e.g. a variable or number) on both sides of the operator. Unary operators require an expression before or after the operator (depending on the operator). Ternary operators require three expressions. With some exceptions, it is an error to exclude an expression:

let ripe = true;
let tasty = true;
if (ripe && ) {
  console.log("delicious!")+;
}

To fix this error, add an expression, or remove the extraneous operator:

let ripe = true;
let tasty = true;
if (ripe && tasty) {
  console.log("delicious!");
}

Note that sometimes, it appears that expressions can be omitted, but some operators are binary and unary, and some operators look like other operators conjoined. In these cases, the code might be completely valid, so quick-lint-js won't report any error:

3**5       // different than: 3 * * 5
3<<5       // different than: 3 < < 5
7 + - 8    // same as: 7 + (-8)

E027: missing semicolon after statement

If multiple statements are on the same line, they must be separated with a semicolon (;):

console.log("hello") console.log("world")

$("#message").text("Logged in")fadeIn()

function stop() { /*...*/ }
let shouldStop = false
if (shouldStop) stop() return

To fix this error, add a semicolon, break the line, or use a dot (.) to call a method:

console.log("hello")
console.log("world")

$("#message").text("Logged in").fadeIn()

function stop() { /*...*/ }
let shouldStop = false
if (shouldStop) { stop(); return }

E028: number literal contains consecutive underscores

Number literals can contain underscores (_) to separate digits for legibility. At most one _ can be used between a pair of digits:

let PIN_LED = 0b0__1;
const tau = 3.14159____26536 * 2;

To fix this error, remove extraneous underscores:

let PIN_LED = 0b0_1;
const tau = 3.14159_26536 * 2;

E029: number literal contains trailing underscores

Number literals can contain underscores (_) to separate digits for legibility. Underscores can only appear between digits, not after all digits:

let PIN_UART = 0b00_01;
let PIN_LED  = 0b01_;
const tau = 3.1415926536__ * 2;

To fix this error, remove the trailing underscores, or write more digits:

let PIN_UART = 0b00_01;
let PIN_LED  = 0b01_01;
const tau = 3.1415926536 * 2;

E030: octal literal may not have exponent

Decimal number literals can contain exponents. Octal number literals, which start with an extra 0 digit, cannot contain exponents:

const googol = 01e+100;

To fix this error, make the number literal a decimal number literal by removing the extra leading 0:

const googol = 1e+100;

E031: octal literal may not have decimal

Decimal number literals can contain a decimal (fraction). Octal number literals, which start with an extra 0 digit, cannot contain a decimal:

const PI = 03.14;

To fix this error, make the number literal a decimal number literal by removing the extra leading 0:

const PI = 3.14;

E032: legacy octal literal may not be BigInt

Decimal number literals can be BigInt with an n suffix. Legacy octal number literals, which start with an extra 0 digit, cannot be suffixed with n:

const ID = 012127638745381751821n;
const perms = 07750775077507750775n;

To fix this error, make the number literal a decimal number literal by removing the extra leading 0, or use the 0o to make the a modern octal literal:

const ID = 1234567890123456789n;
const perms = 0o0775_0775_0775_0775_0775n;

E033: redeclaration of global variable

Global variables listed in quick-lint-js.config with "shadowable": false cannot be re-declared in the global scope by a JavaScript module or script:

let window = new windowlib.Window();

let $ = (selector) => document.querySelectorAll(selector);
$('#banana')[0].peel();

To fix this error, choose a different variable name, or put the variable (and code which uses the variable) into a function:

let qsa = (selector) => document.querySelectorAll(selector);
qsa('#banana')[0].peel();

function createUI() {
  let myWindow = new windowlib.Window();
}
createUI();

E034: redeclaration of variable

In a given function or {} block, a variable can only be declared multiple times if it is declared with var or function. Other types of variables can be declared only once:

let x, y, y, w;

const friends = loadFriends();
const friends = friends.filter(friend => friend.name !== "strager");

class Orange { name = "orange" }
class Orange { name = "banana" }

function jump(player, height) {
  let height = height || player.height/2;
}

To fix this error, assign to the existing variable, choose a different variable name, or delete the extra variable:

let x, y, z, w;

let friends = loadFriends();
friends = friends.filter(friend => friend.name !== "strager");

class Orange { name = "orange" }
class Banana { name = "banana" }

function jump(player, height) {
  height = height || player.height/2;
}

E035: RegExp literal flags cannot contain Unicode escapes

Regular expression literals can contain flags. These flags must not be escaped using a Unicode escape sequence:

const isContentLength = /content-length/\u{69}.test(headerName);

To fix this error, stop being clever; write the flag letter directly:

const isContentLength = /content-length/i.test(headerName);

E039: unclosed regexp literal

Regular expression literals start with / and end with /. The / symbol is also used for the division operator. It is a syntax error to omit the trailing / from a regular expression literal:

// The final / is escaped by \.
let LINE_CONTINUATION_RE = / +\/m;

function feetToCentimeters(feet) {
    // The / is interpreted as the start of a regular
    // expression, not the division operator.
    return / 3.28 * 100;
}

To fix this error, close the regular expression literal:

let LINE_CONTINUATION_RE = / +\\/m;

Alternatively, include an expression before / to treat the / as a division operator:

function feetToCentimeters(feet) {
    return feet / 3.28 * 100;
}

E040: unclosed string literal

String literals start with " or ' and end with " or ', respectively. It is a syntax error to omit the trailing " or ' from a string literal. A missing terminator can happen for a number of reasons:

// The final " is escaped by \.
let temp = "c:\temp\";

// String literals cannot span multiple lines.
let poemByIanJohnson = "My code fails. I do not know why.
My code works. I do not know why.";

let unfinishedThought = "The solution to all of our problems is

To fix this error, ensure a backslash (\) is not escaping the terminator, use a template literal for multi-line strings, or just include a terminator:

let temp = "c:\\temp\\";

let poemByIanJohnson = `My code fails. I do not know why.
My code works. I do not know why.`;

let unfinishedThought = "The solution to all of our problems is";

E042: unexpected '@'

In JavaScript, @ is only allowed in string and template literals. It is a syntax error to write @ anywhere else:

@  // oops

// JavaScript does not support C# verbatim strings:
let notepadPath = @"C:\Windows\System32\notepad.exe";

To fix this error, remove the @:

let notepadPath = "C:\\Windows\\System32\\notepad.exe";

E043: unexpected '\' in identifier

Identifiers (variable names, etc.) can contain Unicode escape sequences (\u{69} for example). It is an error for an identifier to have a backslash which is not part of a Unicode escape sequence:

function identity\(x) { return x; }

let bird\U3600 = new ChirpSound();

To fix this error, remove the backslash, or complete the Unicode escape sequence:

function identity(x) { return x; }

let bird\u3600 = new ChirpSound();

E063: missing operator between expression and arrow function

The left-hand side of => must be a list of parameters. It is a syntax error if the left-hand side looks like a function call:

let fs = require("fs");
let path = process.argv[2];
fs.readFile(path (err, data) => {
  console.log(data);
});

To fix this error, make the left-hand side of => valid by adding an operator (usually ,) before the parameter list:

let fs = require("fs");
let path = process.argv[2];
fs.readFile(path, (err, data) => {
  console.log(data);
});

E077: function call before declaration in blocked scope

A function can't be called before its declaration in block scope in Safari.

f();
{
    function f() {}
}

To fix this error, move the function call below the block scope in which it is declared:

{
    function f() {}
}
f();

Another way to fix this error, move the function out of the block scope in which it is declared.

f();
function f() {}
{
}

OR

f();
{
}
function f() {}

E086: redundant delete statement on variable

The following delete statement is redundant on variable:

let x = 3;
delete x;
console.log(x);

To fix this warning, remove the delete statement:

let x = 3;
console.log(x);

E095: Unicode byte order mark (BOM) cannot appear before #! at beginning of script

A script cannot have Unicode byte order mark (BOM) before #!

#!/usr/bin/env node
let x = 3;
console.log(x);

To fix this error, remove the Unicode BOM before #!

#!/usr/bin/env node
let x = 3;
console.log(x);

E133: error generator function star belongs before name

The following code has misplaced '*'.

*function f(x) { yield x; }

To fix this error, move the '*' before function name.

function *f(x) { yield x; }

E160: unexpected '=>'; expected parameter for arrow function, but got an expression instead

The left-hand side of => must be a list of parameters. It is a syntax error if the left-hand side is instead an expression (such as a property access or a function call):

if (this.mapSize => this.capacity) {
  throw new Error("too many items");
}

let fs = require("fs");
let path = process.argv[2];
fs.mkdir(path () => console.log("done"));

To fix this error, replace => with the intended operator, such as >=:

if (this.mapSize >= this.capacity) {
  throw new Error("too many items");
}

Alternatively, make the left-hand side of => valid by adding an operator (usually ,) before the parameter list:

let fs = require("fs");
let path = process.argv[2];
fs.mkdir(path, () => console.log("done"));

E164: JSON syntax error

quick-lint-js configuration files (named quick-lint-js.config or .quick-lint-js.config) contain valid JSON (according to RFC8259). quick-lint-js cannot read a configuration file with malformed JSON:

{
    "globals": {
        // Google Analytics
        "ga": true,
        "google": true,
    }
}

Common mistakes in JSON are trailing commas (disallowed) and comments (disallowed).

To fix this error, correct mistakes in the JSON syntax for your configuration file:

{
    "globals": {
        " // Google Analytics": false,
        "ga": true,
        "google": true
    }
}

E165: TypeScript style const field

const fields are only allowed in TypeScript, not JavaScript

class C {
  const f = null;
} 

To fix this error, remove the const declarator from the field

class C {
  f = null;
} 

E166: "globals" descriptor "shadowable" property must be a boolean

In a quick-lint-js configuration file, a entry in "globals" can have a descriptor object. A descriptor's "shadowable" property must be either true, false, or omitted.

{
    "globals": {
        "gsap": {
          "shadowable": 0
        }
    }
}

To fix this error, make the "shadowable" property true or false:

{
    "globals": {
        "gsap": {
          "shadowable": false
        }
    }
}

E167: "globals" descriptor "writable" property must be a boolean

In a quick-lint-js configuration file, a entry in "globals" can have a descriptor object. A descriptor's "writable" property must be either true, false, or omitted.

{
    "globals": {
        "gsap": {
          "writable": 0
        }
    }
}

To fix this error, make the "writable" property true or false:

{
    "globals": {
        "gsap": {
          "writable": false
        }
    }
}

E168: "globals" must be an object

In a quick-lint-js configuration file, "globals" must be an object or omitted. It is an error if "globals" is an array, a boolean, a number, a string, or null:

{
    "globals": [
        "ga",
        "google",
        "$"
    ]
}

To fix this error, make "globals" an object:

{
    "globals": {
        "ga": true,
        "google": true,
        "$": true
    }
}

E169: "global-groups" must be a boolean or an array

In a quick-lint-js configuration file, "global-groups" must be an array of strings, a boolean, or omitted. It is an error if "global-groups" is a boolean, a number, an object, a string, or null:

{
    "global-groups": {
        "ecmascript": true,
        "browser": true
    }
}

To fix this error, make "global-groups" an array:

{
    "global-groups": [
        "ecmascript",
        "browser"
    ]
}

E170: "global-groups" entries must be strings

In a quick-lint-js configuration file, items in the "global-groups" array must be strings. It is an error if an item is an array, a boolean, a number, an object, or null:

{
    "global-groups": [
        "ecmascript",
        2020,
        "browser"
    ]
}

To fix this error, remove non-string items in "global-groups":

{
    "global-groups": [
        "ecmascript",
        "browser"
    ]
}

E171: "globals" descriptor must be a boolean or an object

In a quick-lint-js configuration file, each entry in "globals" must be a boolean or a descriptor object. It is an error if a "globals" item is an array, a number, a string, or null:

{
    "globals": {
        "gsap": "true"
    }
}

To fix this error, make the "globals" entry true or false:

{
    "globals": {
        "gsap": true
    }
}

E202: missing '=' after variable

The following code has a missing equal '=' after variable name.

let x new Array();

To fix this error, add '=' after variable x.

let x = new Array();

E204: error generator function star belongs after keyword function

The following code has misplaced '*'.

let x = *function(y) { yield y; };

To fix this error, move the '*' after the keyword function.

let x = function*(y) { yield y; };

E205: error missing initializer in const declaration

The following code is missing initialization for const variable declaration.

const x;

To fix this error, initialize the variable x with some value.

const x = 10;

Another way to fix this error, change const to let.

let x;

E206: error label named await not allowed in async function

The following code is using label named 'await' in an async function.

async function f() {
  await:
}

To fix this error, rename label await to something else.

async function f() {
  label:
}

Another way to fix this error, make 'f' a normal function rather than an async function.

function f() {
  await:
}

E207: code point in Unicode escape sequence must not be greater than U+10FFFF

The following code has escaped code point in Unicode out of range.

let x = "hello\u{abcdef}";

To fix this error, make sure that the escaped code point is between U+0000 and U+10FFFF inclusive.

let x = "hello\u{abcde}";

E208: cannot access private identifier outside class

The following code is accessing a private identifier outside the class.

class C {
  #x = 10;
}

function f(c) {
  c.#x = 20;
}

To fix this error, move function f as a static member of class C .

class C {
  #x = 10;
  static f(c) {
    c.#x = 20;
  }
}

Another way to fix this error, remove # before variable x.

class C {
  x = 10;
}

function f(c) {
  c.x = 20;
}