Course:Internet & Tools/
Lesson

Not all errors are created equal. Some prevent your code from running at all. Others only surface when a specific condition is met during execution. And some don't show any error at all, the code just does the wrong thing. Knowing which category an error falls into tells you where to look and how to fix it.

The three categories

There are three distinct categories of error you'll encounter:

  1. Syntax errors: invalid code that the JavaScript engine can't parse. Nothing in the file runs.
  2. RuntimeWhat is runtime?The environment that runs your code after it's written. Some languages need a runtime installed on the machine; others (like Go) bake it into the binary. errors: valid code that crashes when a specific line executes. Everything before the crash runs fine.
  3. Logic errors: code that runs without errors but produces the wrong result.

Each one requires a different debugging approach.

02

Syntax errors

Syntax errors are detected at parse time, before a single line of your code runs. The JavaScript engine reads the file, finds invalid syntax, and refuses to execute anything.

// This entire file fails because of the missing comma
console.log('Starting...'); // Will NOT print

const config = {
  host: 'localhost'
  port: 3000          // SyntaxError: Unexpected identifier 'port'
};

console.log('Ready'); // Will NOT print

Common causes of syntax errors:

// Missing closing brace
function greet() {
  console.log('hello');
// SyntaxError: Unexpected end of input

// Missing comma in an object
const obj = {
  a: 1
  b: 2  // SyntaxError: Unexpected identifier
};

// Invalid assignment target
5 = x; // SyntaxError: Invalid left-hand side in assignment

// Unclosed string
const msg = 'hello; // SyntaxError: Invalid or unexpected token
Because syntax errors prevent the entire file from running, they are usually the easiest to fix, your editor will show a red underline before you even run the code.
03

RuntimeWhat is runtime?The environment that runs your code after it's written. Some languages need a runtime installed on the machine; others (like Go) bake it into the binary. errors

Runtime errors happen while code is executing. The syntax is perfectly valid; something just goes wrong when JavaScript actually evaluates a specific line.

console.log('Starting...'); // Prints ✓

function getUsername(user) {
  return user.name; // TypeError if user is null or undefined
}

console.log('About to get user...'); // Prints ✓
getUsername(null);                   // Crashes here ✗
console.log('Done');                 // Never reached

Notice that code before the error runs fine. That's the key difference from syntax errors. You can use this to narrow down where to look: find the last line that ran successfully, then look at the next line.

// Another runtime error - valid syntax, wrong at execution time
const data = null;
const names = data.map(x => x.name); // TypeError: Cannot read properties of null

// And one that only triggers conditionally
function divide(a, b) {
  return a / b; // Returns Infinity for b=0, not an error in JS
}

function getItem(arr, index) {
  return arr[index].name; // Only crashes if arr[index] is undefined
}

Runtime errors are trickier to catch because they might only appear in certain situations, for example, when a user submits a form with missing fields, or when an APIWhat is api?A set of rules that lets one program talk to another, usually over the internet, by sending requests and getting responses. returns an unexpected shape.

04

Logic errors

Logic errors are the most deceptive category. The code runs without any errors at all, but the output is wrong.

// No errors, but wrong behavior
function applyDiscount(price) {
  if (price > 100) {
    return price * 0.9; // 10% off - correct
  }
  return price * 1.1; // BUG: should return price unchanged, not increase it
}

console.log(applyDiscount(50));  // Returns 55 - wrong, no error thrown
console.log(applyDiscount(200)); // Returns 180 - correct

Logic errors require you to think through what the code should do versus what it actually does. console.log statements and writing tests are your main tools here.

05

Catching errors before they reach users

The best strategy is to catch errors as early in the development process as possible. There are three tools that help with this.

Linters (ESLint)

A linterWhat is linter?A tool that scans your code for style violations, common mistakes, and suspicious patterns without running it. analyzes your code as you type and flags potential problems before you run anything. It catches things like using a variable before declaring it, calling undefined methods, and common logic mistakes.

// ESLint would flag all of these:
if (x = 5) { }           // Warning: Assignment in condition - did you mean ===?
var name = 'Alice';      // Warning: prefer const or let over var
const unused = 'hello';  // Warning: 'unused' is declared but never read

TypeScript

TypeScript adds type annotations to JavaScript and checks them before you run the code. It catches an entire class of runtimeWhat is runtime?The environment that runs your code after it's written. Some languages need a runtime installed on the machine; others (like Go) bake it into the binary. errors at compile time.

// TypeScript catches the wrong argument type before you run anything
function greet(name: string) {
  return 'Hello ' + name.toUpperCase();
}

greet(42); // Error: Argument of type 'number' is not assignable to parameter of type 'string'
// Plain JavaScript - same mistake, but only caught at runtime
function greet(name) {
  return 'Hello ' + name.toUpperCase();
}

greet(42); // TypeError: name.toUpperCase is not a function

Defensive coding patterns

Even without TypeScript, you can write code that handles bad inputs gracefully instead of crashing.

// Check types before using them
function processData(data) {
  if (!Array.isArray(data)) {
    throw new Error('Expected an array, got ' + typeof data);
  }
  return data.map(x => x * 2);
}

// Use optional chaining to avoid property access errors
const city = user?.address?.city; // undefined instead of crash

// Provide default values for function parameters
function renderList({ items = [], title = 'List' } = {}) {
  return items.map(item => `${title}: ${item}`);
}
06

Quick reference

Error typeWhen detectedDoes any code run?Example
SyntaxParse time (before execution)NoMissing }, missing comma
RuntimeDuring executionYes, until the crashnull.name, calling undefined
LogicNever (no error thrown)Yes, everything runsWrong formula, off-by-one

The earlier you catch an error in the development process, the cheaper it is to fix. A linterWhat is linter?A tool that scans your code for style violations, common mistakes, and suspicious patterns without running it. catches problems as you type. TypeScript catches type issues before you run. Tests catch logic errors before users do.