Skip to content

Fix load function to prevent errors when re-evaluated ElixirLS#138

Merged
FelonEkonom merged 2 commits intomembraneframework:masterfrom
Renlor:patch-1
Apr 1, 2026
Merged

Fix load function to prevent errors when re-evaluated ElixirLS#138
FelonEkonom merged 2 commits intomembraneframework:masterfrom
Renlor:patch-1

Conversation

@Renlor
Copy link
Copy Markdown
Contributor

@Renlor Renlor commented Mar 31, 2026

Attempt to resolve a re-evaluation error in Bundlex.Project.load/1 where the function will fail if called more than once in the same session.

Code.require_file/1 returns {module, bytecode} tuples on the first call, but returns nil on subsequent calls. When ElixirLS triggers a recompile in the same session, Code.require_file/1 returns nil.

an exception was raised:
    ** (FunctionClauseError) no function clause matching in Keyword.keys/1
        (elixir 1.19.5) lib/keyword.ex:652: Keyword.keys(nil)
        (bundlex 1.5.4) lib/bundlex/project.ex:196: Bundlex.Project.load/1
        (bundlex 1.5.4) lib/bundlex/project.ex:175: Bundlex.Project.get/1
        (bundlex 1.5.4) lib/mix/tasks/compile.bundlex.ex:29: Mix.Tasks.Compile.Bundlex.run/1
        (mix 1.19.5) lib/mix/task.ex:499: anonymous fn/3 in Mix.Task.run_task/5
        (mix 1.19.5) lib/mix/task.compiler.ex:299: Mix.Task.Compiler.run_compiler/2
        (mix 1.19.5) lib/mix/task.compiler.ex:287: Mix.Task.Compiler.run/4
        (mix 1.19.5) lib/mix/tasks/compile.all.ex:75: Mix.Tasks.Compile.All.do_run/2
        (mix 1.19.5) lib/mix/sync/lock.ex:122: Mix.Sync.Lock.with_lock/3
        (mix 1.19.5) lib/mix/task.ex:499: anonymous fn/3 in Mix.Task.run_task/5
        (mix 1.19.5) lib/mix/tasks/compile.ex:145: Mix.Tasks.Compile.run/1
        (mix 1.19.5) lib/mix/task.ex:499: anonymous fn/3 in Mix.Task.run_task/5
        (language_server 0.30.0) lib/language_server/build.ex:566: ElixirLS.LanguageServer.Build.run_mix_compile/1
        (language_server 0.30.0) lib/language_server/build.ex:198: ElixirLS.LanguageServer.Build.handle_compile_phase/6
        (stdlib 7.2) timer.erl:599: :timer.tc/2
        (language_server 0.30.0) lib/language_server/build.ex:22: anonymous fn/3 in ElixirLS.LanguageServer.Build.build/3

Not sure I am approaching fixing this problem appropriately, it feels quite hack-ish as-is. Please let me know what you think.

Copilot AI review requested due to automatic review settings March 31, 2026 00:55
@Renlor Renlor requested a review from FelonEkonom as a code owner March 31, 2026 00:55
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Fixes Bundlex.Project.load/1 so it no longer crashes when re-evaluated in the same VM session (e.g., ElixirLS-triggered recompiles) by handling Code.require_file/1 returning nil on subsequent calls.

Changes:

  • Add a fallback to Code.compile_file/1 when Code.require_file/1 returns nil, preventing Keyword.keys(nil) crashes.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +196 to +198
modules =
(Code.require_file(bundlex_file_path) || Code.compile_file(bundlex_file_path))
|> Keyword.keys()
Copy link

Copilot AI Mar 31, 2026

Choose a reason for hiding this comment

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

Code.compile_file/1 will recompile and re-evaluate bundlex.exs every time load/1 is called after the file has been required once (since Code.require_file/1 will keep returning nil). That can add noticeable overhead and may emit redefining module ... warnings / re-run any side effects in bundlex.exs. Consider first attempting to recover the project module(s) from already-loaded modules whose module_info(:compile)[:source] matches bundlex_file_path, and only falling back to Code.compile_file/1 when none are currently loaded (e.g., after purge/reload).

Copilot uses AI. Check for mistakes.
Comment on lines +196 to +198
modules =
(Code.require_file(bundlex_file_path) || Code.compile_file(bundlex_file_path))
|> Keyword.keys()
Copy link

Copilot AI Mar 31, 2026

Choose a reason for hiding this comment

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

This change fixes a regression scenario (calling Bundlex.Project.get/1/load/1 more than once in the same VM), but it isn’t covered by tests. Please add an ExUnit test that loads a project once, clears Bundlex.Project.Store (or restarts the agent), and then loads again in the same test process to ensure it doesn’t crash when Code.require_file/1 returns nil.

Copilot uses AI. Check for mistakes.
@mat-hek mat-hek added this to Smackore Mar 31, 2026
@mat-hek mat-hek moved this to In Review in Smackore Mar 31, 2026
@FelonEkonom FelonEkonom self-requested a review April 1, 2026 15:48
Copy link
Copy Markdown
Member

@FelonEkonom FelonEkonom left a comment

Choose a reason for hiding this comment

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

I will fix compilation warnings on my own and release a new patch on hex.pm. Thanks for the contribution 🎉

@FelonEkonom FelonEkonom merged commit cc3593a into membraneframework:master Apr 1, 2026
0 of 3 checks passed
@github-project-automation github-project-automation bot moved this from In Review to Done in Smackore Apr 1, 2026
@Renlor Renlor deleted the patch-1 branch April 1, 2026 20:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

4 participants