How to fix TypeError: value is not a function or its return value is not a promise in Node.js
This error occurs when code attempts to use a non-function value as a function, or when a function is expected to return a promise but returns a non-thenable value instead. It commonly happens in promise chains, async/await operations, or when working with promise constructors.
Quick fix
Fixes TypeError
// Check if value is actually a function
console.log('Type:', typeof myValue);
console.log('Value:', myValue);
// For promises, check if it's thenable
console.log('Is thenable:', myValue && typeof myValue.then === 'function');- Verify the value type causing the error
- Fix Promise constructor with executor function
- Ensure promise chain handlers return promises
- Check for missing semicolons with require statements
// Check if value is actually a functionconsole.log('Type:', typeof myValue);console.log('Value:', myValue);// For promises, check if it's thenableconsole.log('Is thenable:', myValue && typeof myValue.then === 'function');TypeError: value is not a function or its return value is not a promise
What this error means
This TypeError indicates one of two distinct problems in your Node.js code. First, it may mean you're trying to call something as a function that isn't actually a function—like calling `myVariable()` when `myVariable` is a string, number, or undefined. Second, and more specific to promises, it occurs when code expects a promise or thenable object but receives a value that doesn't implement the promise interface. The error is particularly common in promise-based code where functions are expected to return promises but instead return regular values, or where promise handlers are misconfigured. The JavaScript runtime enforces strict typing for promise operations, and this error acts as a guard against improper promise usage. Understanding this error requires recognizing that in JavaScript's promise ecosystem, a "thenable" is any object with a `.then()` method. When the runtime encounters a value that should be thenable but isn't, or when a supposed function isn't callable, it throws this error to prevent further execution problems.
Typical symptoms
- Promise chain breaks with TypeError about values not being functions
- async/await operations fail when trying to await a value
- Code throws "is not a function" error on promise resolution
- .then() or .catch() methods cannot be called on return values
- Promise constructor fails with "resolver undefined is not a function"
- Function calls on module imports fail unexpectedly
Common causes
- Calling a variable or property as a function when it contains a non-function value
- Promise constructor invoked without an executor function: new Promise() instead of new Promise((resolve, reject) => {...})
- Function returns a non-promise value but is used in a promise chain expecting a thenable
- Attempting to call .then() or .catch() on a value that is not a promise
- Missing semicolons causing JavaScript to interpret code incorrectly, especially with require() statements
- Typo in function or method names causing undefined values to be called as functions
- Async function incorrectly returns a non-promise value when a promise is expected
- Promise handler callbacks return values without wrapping them in promises when chaining requires promises
How to fix "TypeError: value is not a function or its return value is not a promise"
Add console.log or debugger statements to check what the value actually is before attempting to use it:
// Check if value is actually a function
console.log('Type:', typeof myValue);
console.log('Value:', myValue);
// For promises, check if it's thenable
console.log('Is thenable:', myValue && typeof myValue.then === 'function');This will help you identify whether you're dealing with a function-calling error or a promise-related error.
If you're creating a promise, ensure you pass an executor function to the constructor:
// Wrong - missing executor function
const myPromise = new Promise();
// Correct - provide executor function
const myPromise = new Promise((resolve, reject) => {
// Your async operation here
setTimeout(() => {
resolve('Success!');
}, 1000);
});The executor function must accept resolve and reject parameters.
When chaining promises, make sure each handler returns a promise if the next .then() expects one:
// Wrong - returning non-promise in chain expecting promises
fetchData()
.then(data => {
return data.id; // Returns a number, not a promise
})
.then(fetchUserById); // Expects a promise, gets a number
// Correct - explicitly return a promise
fetchData()
.then(data => {
return Promise.resolve(data.id);
})
.then(id => fetchUserById(id));
// Better - let the function handle the promise
fetchData()
.then(data => fetchUserById(data.id))
.then(user => console.log(user));Add semicolons after require() statements to prevent JavaScript from misinterpreting your code:
// Wrong - missing semicolon can cause issues
const express = require('express')
(async () => {
// This looks like you're trying to call express as a function
})()
// Correct - add semicolon
const express = require('express');
(async () => {
// Now correctly interpreted as separate statements
})();Enable a linter like ESLint with semicolon rules to catch these automatically.
Ensure async functions properly return promises and await is used correctly:
// Wrong - async function not returning a promise
async function getData() {
const data = fetchSomething(); // Missing await
return data.value; // data might not be resolved yet
}
// Correct - properly await promise resolution
async function getData() {
const data = await fetchSomething();
return data.value;
}
// Also correct - return the promise directly
async function getData() {
return fetchSomething().then(data => data.value);
}Remember that async functions always return promises, even if you return a regular value.
Check for typos in function names that might cause undefined values to be called:
// Wrong - typo in method name
const result = myObject.proces(); // Should be 'process'
// Check if method exists before calling
if (typeof myObject.process === 'function') {
const result = myObject.process();
} else {
console.error('process method does not exist');
}Use TypeScript or JSDoc type annotations to catch these errors at development time.
Advanced notes
Understanding Thenables: A thenable is any object that implements a .then() method according to the Promises/A+ specification. While all promises are thenables, not all thenables are promises. The JavaScript runtime will attempt to "resolve" thenables by calling their .then() method. If you're returning custom thenable objects, ensure they properly implement the interface with both onFulfilled and onRejected handler parameters.
Promise Resolution Flattening: When a promise's resolution handler returns another promise or thenable, JavaScript automatically "flattens" the chain. This means Promise.resolve(Promise.resolve(5)) eventually resolves to 5, not a nested promise. This flattening behavior can cause issues if you're expecting to receive a promise as a value rather than having it automatically resolved.
Async Function Wrapper Pattern: If you need to use await at the top level of a script (outside of an async function), you can use an immediately-invoked async function expression (IIFE): (async () => { await myAsyncOperation(); })().catch(console.error); This pattern is especially useful in Node.js scripts and is a workaround until top-level await is available in your environment.
Promise Constructor Anti-Pattern: Avoid the "promise constructor anti-pattern" where you wrap a promise-returning function in a new Promise constructor unnecessarily: new Promise((resolve) => resolve(somePromiseReturningFunction())) can simply be somePromiseReturningFunction(). The unnecessary wrapping adds overhead and can introduce bugs.
Error Handling in Promise Chains: Every promise in a chain can potentially throw an error. Use .catch() at the end of chains or wrap async/await calls in try-catch blocks. Unhandled promise rejections can crash Node.js applications in newer versions (with the --unhandled-rejections=strict flag), so proper error handling is critical for production applications.
Frequently asked questions
- What does "TypeError" mean?
- js code. First, it may mean you're trying to call something as a function that isn't actually a function—like calling myVariable() when myVariable is a string, number, or undefined. Second, and more specific to promises, it occurs when code expects a promise or thenable object but receives a value that doesn't implement the promise interface.
- How do I fix "TypeError"?
- This error occurs when code attempts to use a non-function value as a function, or when a function is expected to return a promise but returns a non-thenable value instead. It commonly happens in promise chains, async/await operations, or when working with promise constructors.
- What causes "TypeError"?
- Calling a variable or property as a function when it contains a non-function value Promise constructor invoked without an executor function: new Promise() instead of new Promise((resolve, reject) => {...}) Function returns a non-promise value but is used in a promise chain expecting a thenable
- Is the "TypeError" error serious?
- It is a medium-severity error — more of a blocker than a risk. The steps above resolve it.
Official resources & further reading
- 📚Node.js Official Documentation
- 📖Node.js Process Documentation(Official Docs)
- 📝
- 📝
- 📝