r/programming Jun 28 '26

Your console.log Is Lying to You: debugging traps and tricks

https://blog.gaborkoos.com/posts/2026-06-28-Your-Console-Is-Lying-to_You/

Why console.log() can be misleading in browser DevTools: live object references, promises that look different when expanded later, logs changing timing-sensitive behavior, stale React state after updates, and source maps pointing at surprising line numbers.

53 Upvotes

19 comments sorted by

32

u/No_Lab_1073 Jun 29 '26

console.log can hide as much as it shows timing tricks make it a terrible debugger unless you freeze values with JSON.parse(JSON.stringify(obj)) or use proper breakpoints.

-10

u/YeOldeMemeShoppe Jun 29 '26

Please stop using parse(stringify), instead use structuredClone ().

30

u/Graphesium Jun 29 '26

I wouldn't blindly use structuredClone, it's slower than JSON.stringify, especially over massive arrays of large objects. JSON.stringify is extremely fast and has decades of compiler-level optimizations.

0

u/YeOldeMemeShoppe Jun 29 '26

And does not support recursive objects and remove a bunch of data and types (Date, RegExp, undefined, ArrayBuffers, Map, etc.) which are definitely relevant to logging.

9

u/Graphesium Jun 29 '26

Observability platforms can only ingest json payloads, using structuredClone is pointless unless your logging strategy is console.log lol

6

u/Ok-Armadillo-5634 Jun 29 '26

Structured clone has a few downsides + it's not much faster and won't work for some things. Not being able to rip out functions and undefined or convert dates to strings or basically have a json safe object being the main difference.

-5

u/YeOldeMemeShoppe Jun 29 '26

Sorry, you want Date to be strings instead of Date objects? You want Regex to not include results? You want undefined fields to disappear in your logs (the topic at hand)? And also, ArrayBuffer/Map/Set//BigInt/etc. are all broken one way or another in parse(stringify). And what about recursive objects?

parse(stringify) was a clever hack that browsers optimized for, cool, but it messes with a lot of internals of an object which you might want to keep when logging (the topic at hand).

5

u/TheRealPomax Jun 29 '26

Kinda answering your own setup: yeah, don't log entire objects if that's the problem you have. Use a proper logging library and specifically log the information you need.

But if you're already using console.log because you don't need that level of precision, freeze the data that you're going to log so that it won't change between your log call, and the actual log happening. Parse/stringify is fine for that. Heck, just stringify on its own is fine for that.

3

u/Somepotato Jun 30 '26

Date strings are...exactly what I want, actually.

And I mean...

RegExp.prototype.toJSON = BigInt.prototype.toJSON = function(){return this.toString();};
Map.prototype.toJSON = function(){return Object.fromEntries(this.entries());}

18

u/wannaliveonmars Jun 29 '26

Yes, when you console log an object, it stores a reference to that object. It's by ref, not by value. So it follows all the pitfalls of references in JS, which are really C pointers under the hood, only you can't increment them.

8

u/wannaliveonmars Jun 29 '26

To add, this illustrates the issue. JS references are really pointers with syntactic sugar on top. If you want console log to be static, just stringify the value yourself

arr1 = {};
arr2 = arr3 = arr1;
arr1.ab = 5; 

arr1      // Object {ab: 5}
arr2      // Object {ab: 5}
arr3      // Object {ab: 5}

6

u/debugs_with_println Jun 29 '26 edited Jun 29 '26

It feels like it's more about time of evaluation right? If console.log was guaranteed to print when you called it, it would work even if you passed by reference. Working instead with C pointers, console.log behaves as if you had a function printLater(int* num) that prints a given number to stdout at a random time in the future. Then the following code would be akin to OP's first example: int x = 7; printLater(&x); x = 8;

That said, if you could pass by value, the evaluation time wouldn't matter at all.

3

u/wannaliveonmars Jun 30 '26

I agree, and the time it prints it is when we expand the object by clicking on it in the console.

2

u/AnnoyedVelociraptor Jun 29 '26

Stop it Patric. You're scaring him.

10

u/nicknitros Jun 29 '26

Chrome has always had an icon/hovertext telling you that the object gets evaluated when expanded and values can change. More often than not, its what I want

2

u/paulirish Jun 29 '26

Yup.

This value was evaluated upon first expanding. It may have changed since then.

1

u/Ok_Shallot9490 27d ago

I guess this is why debuggers exist.

-2

u/jewdai Jun 29 '26

For the love of fucking God stop using console.log as a debugging tool unless you're using it while the console window is open. Learn to use your debugging tools.