Skip to main content

How to Resolve "TypeError: .then is not a function" Error in JavaScript

The TypeError: ... .then is not a function is a common error in asynchronous JavaScript. It is a clear signal that you are trying to call the .then() method on a value that is not a Promise. This typically happens when a function that you expect to return a promise either doesn't, or the variable you are using was never a promise to begin with.

This guide will explain the fundamental reason this error occurs, cover the most common mistakes that lead to it, and show you how to write robust code to prevent it.

The Core Problem: .then() is Exclusively for Promises

The .then() method is the primary way to interact with a Promise. A Promise is a special object that represents the eventual completion (or failure) of an asynchronous operation. Think of a Promise as a special container for a future value. The .then() method is the way you "open" that container once the value is ready.

The error is the JavaScript engine telling you, "You asked me to call the .then() function, but the variable you gave me isn't a Promise container, so that function doesn't exist on it."

Example of problem:

// This is a plain object, not a promise.
let notAPromise = { data: 'some value' };

// PROBLEM: Objects do not have a `.then()` method.
notAPromise.then(result => {
console.log(result);
});

Error Output:

Uncaught TypeError: notAPromise.then is not a function

Cause 1 (Most Common): The Function is Not async or Doesn't Return a Promise

This is the most frequent source of the error. You have a function that performs an asynchronous task, but you have forgotten to either mark it as async or to explicitly return the promise.

Problem: a function that does not have an explicit return statement implicitly returns undefined.

function fetchData() {
// This function creates a promise, but it doesn't return it.
// Therefore, the function's return value is `undefined`.
Promise.resolve('some data');
}

// PROBLEM: We are calling .then() on `undefined`.
fetchData().then(data => {
console.log(data);
});

Solution: ensure your asynchronous function always returns a promise. There are two ways to do this:

Marking a function as async automatically ensures that it returns a promise. This is the modern and most readable approach.

// Correct: `async` functions always return a promise.
async function fetchData() {
return Promise.resolve('some data');
}

fetchData().then(data => {
console.log(data); // Output: 'some data'
});

Solution B: Explicitly return the Promise

If you are not using async/await, you must explicitly return the promise object.

// Correct: The promise is explicitly returned.
function fetchData() {
return new Promise(resolve => {
resolve('some data');
});
}

fetchData().then(data => {
console.log(data); // Output: 'some data'
});

Cause 2: The Variable is a Plain Value, Not a Promise

This happens when you have a synchronous value but try to use it in a promise chain.

Example of problem:

function getData() {
// This is a synchronous function that returns a plain object.
return { id: 1, name: 'Alice' };
}

let data = getData();

// PROBLEM: `data` is an object, not a promise.
data.then(result => {
console.log(result);
});

Solution: if the value is already available, you don't need .then(). You can use it directly. If you need to start a promise chain from a synchronous value, you can wrap it with Promise.resolve().

let data = { id: 1, name: 'Alice' };

// Correct: Wrap the synchronous value to start a promise chain.
Promise.resolve(data).then(result => {
console.log(result); // Output: { id: 1, name: 'Alice' }
});

The Solution: How to Prevent the Error

To write "defensive" code, you should ensure that the values you are working with are always promises when you expect them to be.

The Promise.resolve() method is a powerful tool for this. It can take any value, and it will return a promise that resolves with that value. If you pass it a value that is already a promise, it will simply return that same promise.

function processValue(value) {
// This ensures we are always working with a promise,
// regardless of what `value` is.
Promise.resolve(value).then(result => {
console.log('Processed:', result);
});
}

processValue('Hello'); // Works with a plain string
processValue(Promise.resolve('World')); // Works with a promise

Output:

Processed: Hello
Processed: World

Conclusion

The TypeError: .then is not a function is a clear indicator that you are attempting to use a promise-specific method on a value of the wrong type.

To solve it, follow this diagnostic checklist:

  1. Inspect the function call: Is the function you are calling guaranteed to return a promise? Make sure it is either marked as async or has an explicit return new Promise(...).
  2. Inspect the variable: Use console.log() to see what the variable actually is before you call .then() on it. Is it a plain object, a number, undefined?
  3. If you need to handle a value that might or might not be a promise, you can safely wrap it with Promise.resolve(myVar) to ensure you can always chain a .then() call.