Skip to main content

How to Convert an Error Object to a String in JavaScript

When you catch an error in JavaScript, you get an Error object. This object contains valuable information for debugging and logging, but you need to know how to access its properties to convert it into a useful, human-readable string.

This guide will teach you the standard and most effective ways to extract information from an Error object. You will learn the difference between the .message and .stack properties and the best practices for handling errors thrown by third-party libraries.

The Core Problem: Handling the Error Object

When you use a try...catch block, the value caught in the catch (err) block is typically an instance of the Error class. This is an object, not a simple string.

try {
// This will throw an error
const result = nonExistentVariable;
} catch (err) {
console.log(typeof err); // Output: "object"

// Logging the object directly often gives you the most useful info
console.log(err);
/* Output (in Node.js):
ReferenceError: nonExistentVariable is not defined
at Object.<anonymous> (C:\...\index.js:3:18)
... (stack trace)
*/
}

To use this information programmatically, you need to access its specific properties.

Getting the Error Message with err.message

The message property is the most important part of an Error object. It's a human-readable string that describes what went wrong. This is the value you will most often want to log or display to a user.

For example, we need to extract only the descriptive error message from a thrown Error.

// Problem: How to get just the message "Something went wrong"?
const myError = new Error('Something went wrong');

Solution: access the .message property directly.

try {
throw new Error('Could not connect to the database.');
} catch (err) {
const errorMessage = err.message;

console.log('Error Message:', errorMessage);
// Output: Error Message: Could not connect to the database.
}
note

This property provides a clean, concise string that is perfect for logging or displaying in a UI.

Getting the Stack Trace with err.stack

For debugging, the stack property is invaluable. It provides a string containing the error message followed by a "stack trace" of which functions were called, in what order, from which files, and on which lines, leading up to the error.

For example, we need to log the full diagnostic details of an error for debugging purposes.

// Problem: How to get the full call stack for an error?
function functionA() {
functionB();
}
function functionB() {
throw new Error('An error occurred in functionB');
}

Solution: access the .stack property.

try {
functionA();
} catch (err) {
console.log('--- Full Stack Trace ---');
console.log(err.stack);
}

Output (will vary by environment)

--- Full Stack Trace ---
Error: An error occurred in functionB
at functionB (C:\...\index.js:8:9)
at functionA (C:\...\index.js:5:3)
at Object.<anonymous> (C:\...\index.js:12:3)
...
note

The stack trace is read from top to bottom, showing you the exact path the code took to trigger the error.

A Note on Best Practices: Handling Non-Error Objects

While it's a strong convention to only throw instances of the Error class, JavaScript technically allows you to throw anything, including strings or plain objects.

try {
// This is a bad practice, but some libraries might do it.
throw 'A simple string error';
} catch (err) {
// `err` is now a string, not an object. It has no .message property.
console.log(err.message); // Output: undefined
}

To write truly robust error-handling code, you should check if the caught value is an actual Error instance before trying to access its properties.

try {
// ... code that might fail ...
} catch (err) {
let errorMessage;

if (err instanceof Error) {
// It's a proper Error object, so we can reliably access .message
errorMessage = err.message;
} else {
// It's something else (e.g., a string), so we convert it to a string.
errorMessage = String(err);
}

console.log('Caught error:', errorMessage);
}
note

This pattern ensures your catch block will never fail, even if it receives an unexpected error type.

Conclusion

Properly handling Error objects is key to building resilient applications.

  • To get the human-readable error description, use the err.message property. This is what you should typically show to users or use in logs.
  • To get the full debugging information, including the call stack, use the err.stack property. This is ideal for development and error-tracking services.
  • For the most robust error handling, use if (err instanceof Error) to ensure you are dealing with a proper Error object before accessing its properties.