eleventy icon indicating copy to clipboard operation
eleventy copied to clipboard

On watch with global JS data file: Cannot assign to read only property 'source' of object '#<Object>' (via TypeError)

Open kleinfreund opened this issue 1 year ago • 5 comments

Operating system

Windows 11, macOS

Eleventy

3.0.0

Describe the bug

Since upgrading to Eleventy 3.0.0, eleventy --serve is crashing after picking up the first changes to the watched files (i.e. not immediately upon running eleventy --serve).

Error:

[11ty] Problem writing Eleventy templates:
[11ty] Cannot assign to read only property 'source' of object '#<Object>' (via TypeError)
[11ty]
[11ty] Original error stack trace: TypeError: Cannot assign to read only property 'source' of object '#<Object>'
[11ty]     at getMergedItem (C:\Users\phil\dev\kleinfreund.de\node_modules\@11ty\eleventy-utils\src\Merge.js:38:25)
[11ty]     at getMergedItem (C:\Users\phil\dev\kleinfreund.de\node_modules\@11ty\eleventy-utils\src\Merge.js:38:27)
[11ty]     at getMergedItem (C:\Users\phil\dev\kleinfreund.de\node_modules\@11ty\eleventy-utils\src\Merge.js:38:27)
[11ty]     at Merge (C:\Users\phil\dev\kleinfreund.de\node_modules\@11ty\eleventy-utils\src\Merge.js:75:12)
[11ty]     at #getGlobalData (file:///C:/Users/phil/dev/kleinfreund.de/node_modules/@11ty/eleventy/src/Data/TemplateData.js:364:26)
[11ty] Wrote 0 files in 0.03 seconds (v3.0.0)
[11ty] Watching…

Turning on debug mode for Eleventy*, the source of the issue points to global data files:

  Eleventy:FastGlobManager Glob search ('global-data') searching for: [ './src/_data/**/*.{json,mjs,cjs,js}' ] +39ms
  Eleventy:TemplateData Found global data file ./src/_data/metadata.json and adding as: metadata +10ms
  Eleventy:TemplateData Found global data file ./src/_data/eleventy.js and adding as: eleventy +0ms
[11ty] Problem writing Eleventy templates:
  Eleventy:EleventyErrorHandler Full error object: "TypeError: Cannot assign to read only property 'source' of object '#<Object>'\n" + '    at getMergedItem (C:\\Users\\phil\\dev\\kleinfreund.de\\node_modules\\@11ty\\eleventy-utils\\src\\Merge.js:38:25)\n' + '    at getMergedItem (C:\\Users\\phil\\dev\\kleinfreund.de\\node_modules\\@11ty\\eleventy-utils\\src\\Merge.js:38:27)\n' + '    at getMergedItem (C:\\Users\\phil\\dev\\kleinfreund.de\\node_modules\\@11ty\\eleventy-utils\\src\\Merge.js:38:27)\n' + '    at Merge (C:\\Users\\phil\\dev\\kleinfreund.de\\node_modules\\@11ty\\eleventy-utils\\src\\Merge.js:75:12)\n' + '    at #getGlobalData (file:///C:/Users/phil/dev/kleinfreund.de/node_modules/@11ty/eleventy/src/Data/TemplateData.js:364:26)' +0ms
[11ty] Cannot assign to read only property 'source' of object '#<Object>' (via TypeError)
  Eleventy:EleventyErrorHandler (error stack): TypeError: Cannot assign to read only property 'source' of object '#<Object>'
  Eleventy:EleventyErrorHandler     at getMergedItem (C:\Users\phil\dev\kleinfreund.de\node_modules\@11ty\eleventy-utils\src\Merge.js:38:25)
  Eleventy:EleventyErrorHandler     at getMergedItem (C:\Users\phil\dev\kleinfreund.de\node_modules\@11ty\eleventy-utils\src\Merge.js:38:27)
  Eleventy:EleventyErrorHandler     at getMergedItem (C:\Users\phil\dev\kleinfreund.de\node_modules\@11ty\eleventy-utils\src\Merge.js:38:27)
  Eleventy:EleventyErrorHandler     at Merge (C:\Users\phil\dev\kleinfreund.de\node_modules\@11ty\eleventy-utils\src\Merge.js:75:12)
  Eleventy:EleventyErrorHandler     at #getGlobalData (file:///C:/Users/phil/dev/kleinfreund.de/node_modules/@11ty/eleventy/src/Data/TemplateData.js:364:26) +1ms

Deleting src/_data/eleventy.js resolves the issue.

The contents of that file are:

export default {
  isProduction: process.env.NODE_ENV === 'production',
};

The contents don't seem to matter (e.g. removing the access to process doesn't resolve the issue).

Reproduction steps

  1. Set up the reproduction project.

    git clone https://github.com/kleinfreund/kleinfreund.de.git
    cd kleinfreund.de
    git reset --hard https://github.com/kleinfreund/kleinfreund.de/commit/79044f8f1eed33ca7c2aff24c97d4cfbb7688888  # The commit in which I upgraded to Eleventy 3.0.0
    npm install
    
  2. Run npm start and make a file change in a watched file (e.g. src/_includes/layouts/base.liquid).

  3. Observe the watcher output for result 1. Stop the npm start script.

  4. For working behavior comparison: Delete src/_data/eleventy.js.

  5. Repeat step 2 and observe the watcher output for result 2. Stop the npm start script.

  6. For working behavior comparison: Run:

    git reset --hard https://github.com/kleinfreund/kleinfreund.de/commit/a6b5e66f03f651050701e4935d53cc291ad56a3b  # The commit right before I upgraded to Eleventy 3.0.0
    npm install
    
  7. Repeat step 2 and observe the watcher output for result 3. Stop the npm start script.

  8. Delete the reproduction project.

    cd ..
    rm -rf kleinfreund.de
    

Expected behavior

Result 1, 2, and 3 show no errors after the file change.

The actual behavior, however, shows an error in result 1. Result 2 and 3 show the working behavior.

Reproduction URL

https://github.com/kleinfreund/kleinfreund.de

Screenshots

No response

kleinfreund avatar Oct 03 '24 09:10 kleinfreund

This is almost certainly due to reserved data (via your eleventy.js global data file). Sorry the error message is bad!

https://www.11ty.dev/docs/data-eleventy-supplied/#frozen-data

zachleat avatar Oct 15 '24 21:10 zachleat

This is almost certainly due to reserved data (via your eleventy.js global data file). Sorry the error message is bad!

You're quite right indeed. I did figure it had to do with frozen objects but I didn't realize I was looking for this entry in the release notes:

Reserved Eleventy properties in data cascade are now frozen https://github.com/11ty/eleventy/issues/1173 Docs: https://v3.11ty.dev/docs/data-eleventy-supplied/#frozen-data

I guess a better error message would be nice but perhaps the coincidence of someone using a file named eleventy for global data that happens to run into this is quite unlikely.

However, one question: shouldn't this error trigger also on build or first serve?

kleinfreund avatar Oct 16 '24 16:10 kleinfreund

Yeah, for sure. Eleventy does let you merge properties into the eleventy global on build (though not overwriting any existing property names) but errors on second run watch/serve, which is peculiar.

zachleat avatar Oct 16 '24 19:10 zachleat

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze#description notes that not all assignment to frozen objects results in errors 🫠

zachleat avatar Oct 18 '24 22:10 zachleat

For posterity and search engine users, here's how I solved this issue in my site: https://github.com/kleinfreund/kleinfreund.de/commit/c9032dccdc524db2a2f064740f3677324be42074

TL;DR: change the file name of _data/eleventy.js to something else (I picked _data/env.js)


@zachleat I'm happy to close to this as ultimately a user error but of course feel free to leave this open if you do want to/are able to improve the error message in some way.

kleinfreund avatar Oct 20 '24 09:10 kleinfreund

There is some inconsistency happening here, per JavaScript rules writing to a frozen property will error in strict mode (ESM) but currently it’s failing silently (non-strict mode behavior).

So, not great but not harmful. I’ll leave this one open in bug: lite status because there is something to fix here.

zachleat avatar Oct 21 '24 16:10 zachleat