How to fix SyntaxError: await is only valid in async function in Node.js

Node.jsBEGINNERMEDIUMUpdated Dec 9, 2025ยท 230 views

This error occurs when the await keyword is used outside of an async function context. JavaScript requires await to be inside async functions, async generators, or ES module top-level code to properly handle asynchronous operations.

Quick fix

Fixes ERR_PARSE

function fetchData() {
  const response = await fetch('https://api.example.com/data');
  const data = await response.json();
  return data;
}
  1. Mark the enclosing function as async
  2. Fix callback functions in array methods
  3. Enable ES modules for top-level await
  4. Use an async IIFE as a wrapper
node.js โ€” error
function fetchData() {
const response = await fetch('https://api.example.com/data');
const data = await response.json();
return data;
}
SyntaxError: await is only valid in async function

What this error means

This syntax error indicates that you're trying to use the `await` keyword in a location where JavaScript doesn't allow it. The `await` operator can only be used in specific contexts: inside async functions, async generator functions, or at the top level of ES modules. The reason for this restriction is fundamental to how JavaScript handles asynchronous code. When you use `await`, it pauses the execution of the surrounding async context while waiting for a Promise to resolve, but it never blocks the entire JavaScript runtime. Other tasks can continue running. This behavior is only possible within an async context that the JavaScript engine knows how to pause and resume. In Node.js, this error commonly appears when developers forget to mark a function as async, use await in regular callback functions, or try to use await in CommonJS modules without proper setup.

Typical symptoms

  • Code fails to parse or run with a SyntaxError message
  • Application crashes immediately on startup before any code executes
  • Error points to a line with an await keyword
  • IDE or linter shows syntax highlighting errors around await statements
  • Build tools fail with parsing errors during compilation

Common causes

  1. Using await inside a regular function that is not marked with the async keyword
  2. Using await in a callback function (like forEach, map, filter) without making the callback async
  3. Attempting to use await at the top level of a CommonJS script without ES module support
  4. Using await inside a constructor function (constructors cannot be async)
  5. Using await in a class method that is not marked as async
  6. Missing "type": "module" in package.json when using top-level await in .js files

How to fix "SyntaxError: await is only valid in async function"

1Mark the enclosing function as async

The most common fix is to add the async keyword before the function that contains the await statement.

Before (incorrect):

javascript
function fetchData() {
  const response = await fetch('https://api.example.com/data');
  const data = await response.json();
  return data;
}

After (correct):

javascript
async function fetchData() {
  const response = await fetch('https://api.example.com/data');
  const data = await response.json();
  return data;
}

This also applies to arrow functions, methods, and function expressions:

javascript
// Arrow function
const getData = async () => {
  const result = await fetchData();
  return result;
};

// Class method
class DataService {
  async loadData() {
    const data = await this.fetch();
    return data;
  }
}
2Fix callback functions in array methods

A common mistake is using await inside callbacks for array methods like forEach, map, or filter without making the callback function async.

Before (incorrect):

javascript
async function processItems(items) {
  items.forEach(item => {
    const result = await processItem(item); // Error!
    console.log(result);
  });
}

After (correct option 1 - use for...of):

javascript
async function processItems(items) {
  for (const item of items) {
    const result = await processItem(item);
    console.log(result);
  }
}

After (correct option 2 - async callback with Promise.all):

javascript
async function processItems(items) {
  await Promise.all(
    items.map(async (item) => {
      const result = await processItem(item);
      console.log(result);
    })
  );
}

Note: forEach doesn't work well with async/await even if you make the callback async, because it doesn't wait for promises. Use for...of for sequential processing or Promise.all with map for parallel processing.

3Enable ES modules for top-level await

If you need to use await at the top level of your file (outside any function), you must use ES modules instead of CommonJS.

Option 1: Add to package.json

json
{
  "type": "module"
}

Then in your .js files:

javascript
// This now works at the top level
const data = await fetch('https://api.example.com/data');
console.log(await data.json());

Option 2: Use .mjs extension

Rename your file from .js to .mjs:

bash
mv script.js script.mjs

Files with .mjs extension are always treated as ES modules.

Requirements:
- Node.js 14.8.0+ (requires --harmony-top-level-await flag for 14.8-16.11)
- Node.js 16.12.0+ (works by default in ES modules)

Note: When using ES modules, you must use import instead of require:

javascript
// CommonJS (old)
const fs = require('fs');

// ES module (new)
import fs from 'fs';
4Use an async IIFE as a wrapper

If you can't enable ES modules but need to use await at the top level, wrap your code in an async Immediately Invoked Function Expression (IIFE).

Pattern:

javascript
(async () => {
  const response = await fetch('https://api.example.com/data');
  const data = await response.json();
  console.log(data);
})();

With error handling:

javascript
(async () => {
  try {
    const response = await fetch('https://api.example.com/data');
    const data = await response.json();
    console.log(data);
  } catch (error) {
    console.error('Error:', error);
  }
})();

This creates an async function and immediately invokes it, allowing you to use await inside without modifying the module system. This works in both CommonJS and ES modules.

5Convert to Promise chains if needed

If you cannot make the function async (for example, in certain callback scenarios), you can use traditional Promise chains with .then() and .catch().

Using async/await (not always possible):

javascript
const result = await someAsyncFunction();
console.log(result);

Using Promise chains (works anywhere):

javascript
someAsyncFunction()
  .then(result => {
    console.log(result);
  })
  .catch(error => {
    console.error(error);
  });

This approach is useful when:
- You're working with older callback-based APIs
- You're in a context that cannot be made async
- You need to maintain compatibility with older Node.js versions

Advanced notes

Top-Level Await Considerations:

Top-level await in ES modules causes the entire module to behave like an async function. Other modules importing it will wait for any top-level awaits to resolve before executing their own code. This can affect application startup time and module initialization order. Use it judiciously for critical initialization tasks.

Constructor Limitations:

Class constructors cannot be async, and therefore cannot use await. If you need to perform async initialization in a class, use a factory pattern:

javascript
class DataService {
  constructor(data) {
    this.data = data;
  }

  static async create() {
    const data = await fetchInitialData();
    return new DataService(data);
  }
}

// Usage
const service = await DataService.create();

Performance with Array Methods:

When using async callbacks with array methods, understand the difference:
- for...of with await: Sequential execution (slower, but ordered)
- Promise.all with map: Parallel execution (faster, but unordered)
- forEach with async callbacks: Fires all at once but doesn't wait (often not desired)

CommonJS vs ES Modules:

Node.js uses CommonJS by default, which doesn't support top-level await. To check your module type:

bash
# Check package.json
grep '"type"' package.json

# If not found, you're using CommonJS by default

Transpilers and Build Tools:

If using TypeScript, Babel, or other build tools, ensure your target configuration supports async/await:
- TypeScript: Set "target": "ES2017" or higher in tsconfig.json
- Babel: Include @babel/plugin-transform-async-to-generator

Frequently asked questions

What does "ERR_PARSE" mean?
This syntax error indicates that you're trying to use the await keyword in a location where JavaScript doesn't allow it. The await operator can only be used in specific contexts: inside async functions, async generator functions, or at the top level of ES modules. The reason for this restriction is fundamental to how JavaScript handles asynchronous code.
How do I fix "ERR_PARSE"?
This error occurs when the await keyword is used outside of an async function context. JavaScript requires await to be inside async functions, async generators, or ES module top-level code to properly handle asynchronous operations.
What causes "ERR_PARSE"?
Using await inside a regular function that is not marked with the async keyword Using await in a callback function (like forEach, map, filter) without making the callback async Attempting to use await at the top level of a CommonJS script without ES module support
Is the "ERR_PARSE" error serious?
It is a medium-severity error โ€” more of a blocker than a risk. The steps above resolve it.

Official resources & further reading