MethodError: no method matching, but the method exists

I’m getting the following error:

ERROR: MethodError: no method matching choose(::Main.Sim.ModelBasedAgent, ::Int64)
Closest candidates are:
  choose(::Main.Sim.ModelFreeAgent, ::Int64) at /home/xxxxx/Projects/simulateagents.jl:57
  choose(::Main.Sim.ModelBasedAgent, ::Int64) at /home/xxxxx/Projects/simulateagents.jl:53

But there is a matching method. What’s going on?

First of all, welcome to our community! :confetti_ball:

This kind of error often happens if you are using include to include the same file in many parts of your code (include should not be used this way, if this is the case I can point some references to you later). You will end up creating the same type multiple times and they all have the same name and fields but will be incompatible to each other. Without more information is hard to draw a conclusion. Could you provide/point out to your sources (or give an MWE)?

6 Likes

You are right, I had included the file several times in the REPL. Thank you! But then how do you reinclude a file after changing it?

1 Like

You just need to make sure to call include at the toplevel, not inside the same function you are calling the included function from.

I’m not including anything in the file containing my code, I’m including this file in the REPL multiple times (after changing the code).

One option is to use includet from package Revise.jl. You just do the includet a single time, and then when you change and save the file, Revise.jl will silently update the code in the REPL for you.

However, includet only tracks changes to methods, so this will work if you included the same file multiple times because you were changing function code, and ended with the same type multiple times because the definition was there too, but this will not work if you were making changes to the type definition too.

If you change a type definition (struct/mutable struct) then you have to restart the REPL, otherwise the Julia session may be lost at which version of the type you are referring to. (Objects created with an old version of the type will have the same name, but dispatch on the functions defined together with the new type will fail on them, like you perceived.) There are some tricks to deal with changing a type in the middle of a REPL session, but they are considerably limited:

  1. Do not use your type. Use a NamedTuple instead. Dispatch your functions over NamedTuple, and change your fields as much as you want. When you are sure the fields will not change anymore, then replace NamedTuple by your type.
  2. Create an abstract type, dispatch your functions on it, if you make a change to the struct instead create a new struct ending with _2, _3, and so on, all these inherit the abstract type so your functions recognize them,
  3. Put the struct and functions inside a module. When you need to update the struct, change the module name too, include again, and prefix with the new module name.
2 Likes

I had this problem when using JupyterLab (version 2.2.6), but not when running the same code directly in Juila.

I only had includes at the top-level, and apparently wasn’t doing anything else wrong. Either JupyterLab sometimes preforms commands in an unexpected context, it got wedged when an earlier include failed, or it’s a heisenbug.

I spent a lot of time thinking that I didn’t understand dispatch and trying random variations before realizing that the problem only occurred in JupyterLab.

I wasn’t using Jupyter though.

Understood.

I assume that your problem and my problem are related. Although I don’t know precisely what causes either.

The comments suggest that there is a bug, that is only exercised when you do something unusual, probably involving issuing the same include multiple times. But I suspect that whatever surfaces this bug, Jupyter does it somewhat often. As a result this may be a more common bug than is widely understood.