Skip to content

createRequire does not respect deleting module from require.cache #57696

Open

Description

@sdegutis

Version

v23.10.0

Platform

Microsoft Windows NT 10.0.26100.0 x64

Subsystem

No response

What steps will reproduce the bug?

mod.js

console.log('in mod.ts')

testcase.js

import { createRequire } from 'module'
const require = createRequire(import.meta.url)

require('./mod.js?1')

const key = Object.keys(require.cache)[0]
delete require.cache[key]

require('./mod.js?2')

How often does it reproduce? Is there a required condition?

Every time.

What is the expected behavior? Why is that the expected behavior?

in mod.ts
in mod.ts

What do you see instead?

in mod.ts

Additional information

I traced it to this line, which just fully ignores source.

if (status === kEvaluated) {
return { wrap: job.module, namespace: job.module.getNamespaceSync(filename, parentFilename) };

Activity

  1. sdegutis commented on Mar 31, 2025

    @sdegutis
    Author

    For context, this is after I provided source via a custom sync loader which had both resolve and load hooks. I traced the source all the way to this point, and Node.js does not take into account that I had provided a custom source. That's why I consider this a bug.

  2. sdegutis commented on Apr 1, 2025

    @sdegutis
    Author

    Also, I'm using a cache busting query already, but it gets stripped away a few functions up when turned into a filename for the sake of requiring it via CJS resolution, so it's apparently ignored.

  3. ljharb commented on Apr 2, 2025

    @ljharb
    SponsorMember

    require only takes file paths or bare specifiers, not URLs, so no query strings would make sense there.

  4. sdegutis commented on Apr 2, 2025

    @sdegutis
    Author

    @ljharb right but it's a weird hybrid of require and import, because it's in an ESM project and it's an ESM file being imported, but require is called via createRequire, which goes through the hassle of resolving it as if required, but skips require's actual resolution which would use require.cache (Module._cache), and ultimately finds an ESM module, sees that it's already been resolved, and uses that one's exports. Ironically, it's really only using require-logic to skip the cache busting, but in every other area in this code it's acting as if it's ESM. So it's inconsistent. Either it should fully use ESM resolution and see the cache busting query, or it should fully use require-logic and see that I deleted it from require.cache.

  5. ljharb commented on Apr 2, 2025

    @ljharb
    SponsorMember

    I’m confused, if you want to skip the cache busting just import it normally. The only place it makes any sense to require ESM is inside a CJS file.

  6. sdegutis commented on Apr 2, 2025

    @sdegutis
    Author

    @ljharb In this case, I'm using createRequire because it's a sync ESM module (no tlawait) and I'd like to avoid poisining all sync methods involved

  7. ljharb commented on Apr 2, 2025

    @ljharb
    SponsorMember

    I’m still confused - what do you mean by poisoning?

  8. sdegutis commented on Apr 2, 2025

    @sdegutis
    Author

    Interesting, that article gives me a new respect for Go.

  9. ljharb commented on Apr 2, 2025

    @ljharb
    SponsorMember

    ahhh this is something that can't be a static import at the root of the file?

  10. sdegutis commented on Apr 2, 2025

    @sdegutis
    Author

    @ljharb Right, it's dynamically imported/required in a sync context.

  11. jdmarshall commented on Aug 16, 2025

    @jdmarshall

    require('./foo.mjs') also does not honor cache invalidation.

    Anyone have a workaround? I'm trying to migrate a module to ESM while providing backward compat and this is breaking tests.

  12. github-actions commented on Apr 20, 2026

    @github-actions
    Contributor

    This issue has been marked as stale due to 210 days of inactivity.
    It will be automatically closed in 30 days if no further activity occurs. If this is still relevant, please leave a comment or update it to keep it open.

  13. added
    staleIssues and PRs marked stale due to inactivity and scheduled for automatic closure.
    on Apr 20, 2026
  14. jdmarshall commented on Apr 22, 2026

    @jdmarshall

    I have a trick but it only works when importing ESM not CJS, by basically adding a query parameter

  15. removed
    staleIssues and PRs marked stale due to inactivity and scheduled for automatic closure.
    on Apr 23, 2026
  16. github-actions commented on Jul 23, 2026

    @github-actions
    Contributor

    This issue has been marked as stale due to 90 days of inactivity.
    It will be automatically closed in 30 days if no further activity occurs. If this is still relevant, please leave a comment or update it to keep it open.

  17. added
    staleIssues and PRs marked stale due to inactivity and scheduled for automatic closure.
    on Jul 23, 2026
  18. jdmarshall commented on Jul 23, 2026

    @jdmarshall

    This is still an important case particularly for unit testing frameworks.

  19. removed
    staleIssues and PRs marked stale due to inactivity and scheduled for automatic closure.
    on Jul 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions