Skip to content

Return errors instead of raising on corrupt beam in docs and ExCk reads - #348

Merged
lukaszsamson merged 1 commit into
masterfrom
fix-fetch-docs-beam-lib-raise
Oct 18, 2026
Merged

lukaszsamson merged 1 commit into
masterfrom
fix-fetch-docs-beam-lib-raise

Conversation

@lukaszsamson

Copy link
Copy Markdown
Collaborator

Problem

Completion crashes when a .beam is malformed or truncated (e.g. being rewritten by a concurrent compile). Code.fetch_docs/1 delegates to :beam_lib, which only catches throws, so the error escapes:

Exception truncated in report (Elixir 1.17.3 / 1.18.3, completion):
    (stdlib 6.2.2.2) beam_lib.erl:712: :beam_lib.read_info/1
    (elixir 1.18.3) Code.get_beam_and_path/1
    (elixir 1.18.3) Code.fetch_docs/1
    elixir_sense/core/normalized/code.ex:25: ElixirSense.Core.Normalized.Code.get_docs/2
    elixir_sense/core/introspection.ex:638: ElixirSense.Core.Introspection.get_module_docs_summary/2
    (elixir_ls_utils) ElixirLS.Utils.CompletionEngine.get_erlang_module_result/2  (also get_elixir_module_result/2)

Same root cause as #346 (Normalized.Typespec).

Changes

  • Normalized.Code.fetch_docs/1 catches any raise/exit/throw from Code.fetch_docs and returns {:error, :chunk_not_found}. callback_documentation/1 now goes through this wrapper.
  • ExCkReader on-disk :beam_lib.chunks/2 path catches the same and falls through to the existing binary fallback.
  • Not changed: BuiltinFunctions Code.fetch_docs(Module) runs at compile time on a fixed module, so it cannot read an arbitrary beam at request time.

Tests

  • Normalized.CodeTest: corrupt beam (byte flipped in the atom table) makes fetch_docs/1 and get_docs/2 return error/nil. Fails on master with the MatchError above.
  • ExCkReaderTest: same corruption on the on-disk path; asserts read_chunk/2 returns a tagged result and does not raise. Fails on master.

mix test on the touched files: 45 passed. Full suite has the same 58 failures with and without this change (pre-existing ElixirTypes/BindingDescr property tests on the local 1.21-dev toolchain).

Code.fetch_docs/1 delegates to :beam_lib, which only catches throws. A
malformed or truncated .beam makes :beam_lib.read_info/1 raise (e.g.
MatchError from a badarg in binary_to_atom), which escaped completion
and hover via Normalized.Code.get_docs/2 and callback_documentation/1.

- Normalized.Code.fetch_docs/1 now catches any raise/exit/throw and
  returns {:error, :chunk_not_found}; callback_documentation/1 goes
  through it.
- ExCkReader's on-disk :beam_lib.chunks/2 path catches the same and
  falls through to the existing binary fallback.

Tests mirror the typespec corrupt-beam test from #346.
@lukaszsamson
lukaszsamson merged commit 4cbae01 into master Oct 18, 2026
18 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant