Skip to content

Retry invalid anywidget modules#10259

Merged
manzt merged 2 commits into
mainfrom
manzt/invalidate-anywidget-cache
Jul 21, 2026
Merged

Retry invalid anywidget modules#10259
manzt merged 2 commits into
mainfrom
manzt/invalidate-anywidget-cache

Conversation

@manzt

@manzt manzt commented Jul 21, 2026

Copy link
Copy Markdown
Collaborator

Closes #10214

Successful imports were cached before their exports were validated, so reruns could reuse an unusable module. These changes evict modules that fail AFM validation so a fresh URL can be loaded.

Closes #10214

Successful imports were cached before their exports were validated, so
reruns could reuse an unusable module. These changes evict modules that
fail AFM validation so a fresh URL can be loaded.
Copilot AI review requested due to automatic review settings July 21, 2026 16:27
@vercel

vercel Bot commented Jul 21, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
marimo-docs Ready Ready Preview, Comment Jul 21, 2026 6:32pm

Request Review

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes anywidget ESM cache invalidation when a module import succeeds but fails AFM export validation, ensuring reruns can load a fresh URL instead of reusing a cached unusable module (closes #10214).

Changes:

  • Add WidgetDefRegistry.invalidate(jsHash) to explicitly evict a cached module promise by hash.
  • Invalidate the cached module when AFM validation fails (resolveAnyWidget returns null) before throwing the AFM error.
  • Add/extend unit tests to cover invalidation behavior and ensure invalidate is invoked on AFM validation failures.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
frontend/src/plugins/impl/anywidget/widget-binding.ts Adds explicit cache eviction API (invalidate) for module promises keyed by jsHash.
frontend/src/plugins/impl/anywidget/runtime.ts Evicts the cached module when AFM validation fails so subsequent attempts can re-import from a new URL.
frontend/src/plugins/impl/anywidget/tests/widget-binding.test.ts Adds a test asserting invalidation enables a new promise for the same hash with a new URL.
frontend/src/plugins/impl/anywidget/tests/registry.test.ts Adds an assertion that AFM validation failures trigger WIDGET_DEF_REGISTRY.invalidate(spec.hash).

Comment on lines +312 to +323
@@ -318,6 +319,8 @@ describe("WidgetRegistry.getWidget", () => {
await expect(registry.getWidget(testId)).rejects.toThrow(
/missing a default export/,
);
expect(invalidateSpy).toHaveBeenCalledWith(SPEC.hash);
invalidateSpy.mockRestore();

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 4 files

Architecture diagram
sequenceDiagram
    participant UI as Widget UI
    participant RT as Widget Runtime
    participant Mod as Module Loader
    participant Registry as WidgetDefRegistry
    participant Import as Import Cache (#doImport)

    UI->>RT: getWidget(spec)
    RT->>Mod: resolveAnyWidget(mod, url)
    Mod->>Registry: getModule(url, hash)
    
    alt Cache hit (hash exists)
        Registry->>Import: Return cached promise
        Import-->>Registry: Module exports
    else Cache miss
        Registry->>Import: #doImport(url)
        Import-->>Registry: Module exports
        Registry->>Registry: Cache promise for hash
    end
    
    Registry-->>Mod: Module exports
    Mod-->>RT: Widget export or null

    alt Widget export is valid
        RT->>RT: Create WidgetBinding
        RT-->>UI: Widget instance
    else No valid widget export
        RT->>Registry: invalidate(hash)
        RT->>RT: throw getInvalidAnyWidgetModuleError
        Registry->>Registry: Remove hash from #cache
        UI->>UI: Catch error, trigger retry with new URL
        UI->>Registry: getModule(newUrl, sameHash)
        Registry->>Import: #doImport(newUrl)
        Import-->>Registry: Fresh module exports
        Registry-->>UI: Promise for new module
    end
Loading

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread frontend/src/plugins/impl/anywidget/__tests__/registry.test.ts Outdated
@manzt
manzt merged commit 0f8bee7 into main Jul 21, 2026
31 checks passed
@manzt
manzt deleted the manzt/invalidate-anywidget-cache branch July 21, 2026 23:11
@github-actions

Copy link
Copy Markdown
Contributor

🚀 Development release published. You may be able to view the changes at https://marimo.app?v=0.23.15-dev48

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Cache invalidation issues for anywidget js files

3 participants