If you use dbg in a package's interface file, the compiler throws the following error and hangs:
Thread '<unnamed>' panicked at 'called `Option::unwrap()` on a `None` value', crates/compiler/mono/src/ir.rs:6826:18
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Apparently, env.expectation_subs is None here: https://github.com/roc-lang/roc/blob/24e2c661870d9d7c54a5aa8750c334a837af1966/crates/compiler/mono/src/ir.rs#L6808-L6812
I wonder if that is interface specific. I have seen similar errors a lot. That and sometimes debug just not printing. Definitely one of the easier to break features. I think i notice it most in rather nested code, especially if related to tasks.
Oh. I haven't noticed that. In this case the app's main is directly calling the function from the package's interface with the dbg usage in it.
At least in my absolute minimal repro, it is working in an interface:
interface Interface
exposes [someFunc]
imports []
someFunc = \x ->
dbg x
x
So maybe not interface specific. Are you able to share example code where this happens or a repro?
Oh, nevermind, I can repro.
It takes an interface in a package specifically, not an interface in general.
submitted #5185 as a minimal repro.
Nice
Found the root cause of the None in env.expectaction_subs: https://github.com/roc-lang/roc/blob/24e2c661870d9d7c54a5aa8750c334a837af1966/crates/compiler/load_internal/src/file.rs#L2748-L2753
let should_include_expects = (!loc_expects.is_empty() || !loc_dbgs.is_empty()) && {
let modules = state.arc_modules.lock();
modules
.package_eq(module_id, state.root_id)
.expect("root or this module is not yet known - that's a bug!")
};
!loc_dbgs.is_empty() is true because the dbg exists
but .package_eq(module_id, state.root_id) evaluates to false because the module is in a different package
When building applications, you probably don't want to include expects from packages, so that makes sense
However, we still need a way to use dbg and expect when building packages. Maybe this can be a CLI option?
Also, in normal operation, it shouldn't crash because a package contains a dbg or expect
this is an interesting design question...I've gone back and forth on this in the past, but what makes sense to me right now is:
dbg no matter where it comes from. This way if you're debugging a local package on your filesystem, it Just Works.dbg (just take them out before you publish, don't annoy people with your own debugging logic!)expect is trickier because on the one hand it could be annoying if I get a third-party package that's crashing due to failed expects all the time...but on the other hand, wouldn't it be better if I could report that to them? :thinking:
my default thinking is that expect should just always work the same way no matter whether it's a package, and then we can revisit that if it's annoying in practice
Ah cool. So we just need to get rid of that package_eq check, then.
I tried it last night and dbg just started working from packages
Should I make a PR with that change?
sounds good to me! @Folkert de Vries any concerns?
The one annoyance with this is that this will also mean “roc test” will run all tests under a package and all its dependencies, not just local to the module.
That could be made into a separate check though
hm, aren't those separate?
like roc test doesn't have to run top-level expects in other packages
even if it still runs inline expects
Right. I just mean that the implementation, I don't think it is enough to only get rid of the package_eq check.
Yeah, if I get rid of that check, roc test includes expects from packages
and this weird bug shows up if I have both dbgs and expects in a package, roc test hangs, but it works fine if only have one kind :oh_no:
Agus Zubiaga said:
Yeah, if I get rid of that check,
roc testincludesexpects from packages
oh ok, so then the problem is that right after that code we're using should_include_expects to decide whether to include dbgs too
so that line could be used in the else branch too, just with expectations: being empty
could go even further to have that under an else if !loc_dbgs.is_empty() { so we don't bother cloning solved_subs etc if there happen to be no dbgs
Last updated: Nov 28 2025 at 12:16 UTC