Why it happens
JSON.parse() converts anything that is not a string into one, and every plain object becomes the same 15 characters, [object Object]. The parser reads the [ as an array and fails at the o. The value was either parsed already or never serialized. Most common first:
1. Parsing data twice. res.json(), axios’s response.data, jQuery with dataType: 'json' and express.json() already return objects:
const res = await fetch('/api/preferences');
const prefs = await res.json(); // already an object
JSON.parse(prefs); // SyntaxError: "[object Object]" is not valid JSON
2. Sending an object without JSON.stringify. fetch sends a plain-object body as the string [object Object]. The browser shows no error; your server does, when express.json() parses the request:
await fetch('/api/preferences', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: { theme: 'dark', fontSize: 14 }, // sent as "[object Object]"
});
3. Storing an object as text. localStorage.setItem('prefs', prefs), cookie values, URLSearchParams and template literals such as `${prefs}` all produce [object Object]. The error appears on the next read.
4. Low-code nodes. In n8n, fields from an HTTP Request node are already objects, so JSON.parse($json.body) in a Code node fails the same way.
How to fix “[object Object]” is not valid JSON
Parse once, where data enters your program. If a function can receive either form, check the type:
const prefs = typeof input === 'string' ? JSON.parse(input) : input;
fetch and axios
Delete the extra JSON.parse: await res.json() already parsed the body, and axios’s response.data is already an object.
Sending JSON
Serialize the body yourself with fetch:
await fetch('/api/preferences', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ theme: 'dark', fontSize: 14 }),
});
axios serializes plain objects for you, so axios.post('/api/preferences', { theme: 'dark' }) is already correct.
Express
After app.use(express.json()), req.body is the parsed object:
app.use(express.json());
app.post('/api/preferences', (req, res) => {
const { theme, fontSize } = req.body;
res.json({ saved: true, theme, fontSize });
});
If the server logs this error for one client’s requests, the bug is in that client (cause 2).
Storage, cookies and URLs
Write with JSON.stringify(prefs) and read with JSON.parse(...). For values already saved as [object Object], catch the error, remove the key and fall back to defaults. The JSON validator tells you whether a stored value is JSON or this text.
n8n
Use the field as it is, for example $json.body.theme, or write {{ JSON.stringify($json.body) }} where a text field needs JSON.
Same error in other languages
- Python refuses instead of converting:
json.loads({})raisesTypeError: the JSON object must be str, bytes or bytearray, not dict. - A missing value instead of an object gives “undefined” is not valid JSON.
- Firefox reports this case as JSON.parse: unexpected character at line 1 column 2.
The rest of the family is in common JSON errors.