:erlang.get_module_info/1 raises ArgumentError for all modules defined by my application

The title says it all. I have the following project: https://github.com/tmbb/darwin

I get the following:

tmbb@DESKTOP-S472BDT:/mnt/c/Users/tmbb9/Projects/elixir/mutation/darwin$ iex -S mix
Erlang/OTP 21 [erts-10.0.5] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [hipe]

Interactive Elixir (1.8.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> :erlang.get_module_info(Darwin.TestCase)
** (ArgumentError) argument error
    :erlang.get_module_info(Darwin.TestCase)
iex(1)> :erlang.get_module_info(:erlang)        
[
  module: :erlang,
  exports: [
    bitsize: 1,
    check_process_code: 2,
    check_process_code: 3,
    garbage_collect: 1,
    garbage_collect: 2,
    garbage_collect_message_area: 0,
    process_display: 2,
    process_flag: 3,
    setnode: 3,
    suspend_process: 2,
    suspend_process: 1,
    trace_pattern: 2,
    spawn: 2,
    spawn_link: 2,
    spawn_monitor: 3,
    spawn_opt: 2,
    spawn_opt: 3,
    spawn: 4,
    spawn_link: 4,
    spawn_opt: 4,
    spawn_opt: 5,
    crasher: 6,
    yield: 0,
    nodes: 0,
    disconnect_node: 1,
    fun_info: 1,
    send_nosuspend: 2,
    send_nosuspend: 3,
    port_call: 2,
    port_call: 3,
    port_info: 1,
    set_cookie: 2,
    get_cookie: 0,
    integer_to_list: 2,
    integer_to_binary: 2,
    min: 2,
    memory: 0,
    memory: 1,
    module_info: 0,
    module_info: 1,
    localtime_to_universaltime: 1,
    max: 2,
    port_control: 3,
    port_connect: 2,
    port_command: 2,
    port_command: 3,
    port_close: 1,
    open_port: 2,
    ...
  ],
  attributes: [],
  compile: [],
  native: false,
  md5: <<96, 189, 0, 121, 239, 252, 103, 3, 23, 152, 51, 246, 211, 103, 115,
    213>>
]
iex(2)> :erlang.get_module_info(Enum)   
[
  module: Enum,
  exports: [
    __info__: 1,
    all?: 1,
    any?: 1,
    any?: 2,
    at: 2,
    at: 3,
    chunk: 2,
    chunk: 3,
    chunk: 4,
    chunk_by: 2,
    chunk_every: 2,
    chunk_every: 3,
    chunk_every: 4,
    chunk_while: 4,
    concat: 1,
    concat: 2,
    count: 1,
    count: 2,
    dedup: 1,
    dedup_by: 2,
    drop_every: 2,
    drop_while: 2,
    empty?: 1,
    fetch: 2,
    fetch!: 2,
    filter: 2,
    filter_map: 3,
    find: 2,
    find: 3,
    find_index: 2,
    find_value: 2,
    find_value: 3,
    flat_map: 2,
    flat_map_reduce: 3,
    group_by: 2,
    group_by: 3,
    intersperse: 2,
    into: 2,
    into: 3,
    join: 1,
    join: 2,
    map_every: 3,
    map_join: 2,
    map_join: 3,
    map_reduce: 3,
    max: 1,
    max: 2,
    max_by: 2,
    ...
  ],
  attributes: [vsn: [21599393939109611461033790602213369800]],
  compile: [
    options: [
      :dialyzer,
      :no_spawn_compiler_process,
      :from_core,
      :no_auto_import,
      :inline_list_funcs,
      {:inline,
       [
         reduce_enumerable: 3,
         reduce_by: 3,
         reduce: 3,
         entry_to_string: 1,
         aggregate: 3
       ]}
    ],
    version: '7.1.5.2',
    source: '/root/deb/elixir_1.8.2-1/lib/elixir/lib/enum.ex'
  ],
  native: false,
  md5: <<16, 63, 228, 87, 71, 206, 215, 125, 18, 111, 187, 13, 53, 160, 167,
    200>>
]

So, basically, :erlang.get_module_info/1 doesn’t work for modules defined in my aplication but it works for erlang or elixir modules defined in the standard library. I can’t reproduce it with a smaller project or even with other real projects… I have no idea what’s happening. Anyone has a clue?

Well, you’re not supposed to call it directly, as it is not documented. You should call it as MyMod.module_info() instead and it should work because that will load the module (which is the reason why your approach fails):

iex(2)> :erlang.get_module_info(URI)
** (ArgumentError) argument error
    :erlang.get_module_info(URI)
iex(2)> Code.ensure_loaded(URI)
{:module, URI}
iex(3)> :erlang.get_module_info(URI)
[
  module: URI,
5 Likes