Skip to content

type_check_command: "Could not find mutant for type error" crash when the pyrefly reports an error outside any mutant's line range #522

@ejfine

Description

@ejfine

Below is obviously AI-generated (Claude Opus 4.8 FWIW) reproduction and summary of the issue. But I can tell you as a human conclusively that when I run pyrefly on my whole repo I get no errors, and when I run mutmut it gives me this message. So I'm doing my best to file the issue for y'all to be able to track it. Happy to answer any questions

(Unpacked keyword argument `object` is not assignable to parameter `allow_origins` with type `Sequence[str]` in function `starlette.middleware.cors.CORSMiddleware.__init__`). 
Probably, a code mutation influenced types in unexpected locations. 
If your project normally has no type errors and uses mypy/pyrefly, please file an issue with steps to reproduce on github.

mutmut + pyrefly: crash on type errors outside mutant line ranges

mutmut run aborts with an unhandled exception when the configured
type_check_command (here, pyrefly) reports a type error
on a line that is not inside any generated mutant function — for example, a
line in a do_not_mutate file.

Exception: Could not find mutant for type error .../src/repro/consumer.py:12
(Unpacked keyword argument `object` is not assignable to parameter `allow_origins`
 with type `Sequence[str]` in function `starlette.middleware.cors.CORSMiddleware.__init__`).
Probably, a code mutation influenced types in unexpected locations.
If your project normally has no type errors and uses mypy/pyrefly, please file an
issue with steps to reproduce on github.

Reproduce

mutmut-pyrefly-repro.zip

uv sync
uv run mutmut run     # crashes during "Filtering mutations with type checker"

(uv.lock is committed so the versions are pinned: mutmut is the git revision
e92d763, pyrefly 1.0.0.)

What happens

mutmut mutates src/repro/model.py. src/repro/consumer.py is listed under
do_not_mutate, so no mutant functions are generated in it. mutmut writes all
mutants into the mutants/ working tree and runs pyrefly once over it. pyrefly
reports type errors inside consumer.py, and mutmut tries to attribute each error
to a mutant by line-range containment:

mutmut/mutation/file_mutation.py (filter_mutants_with_type_checker):

mutant = next(
    (m for m in mutated_methods if m.line_number_start <= error.line_number <= m.line_number_end),
    None,
)
if mutant is None:
    raise Exception(f"Could not find mutant for type error ...")

Because consumer.py has no mutant methods, mutant is None and mutmut raises,
aborting the whole run. There is no fallback (e.g. skip the error, attribute it to
the file, or just run the tests for affected mutants).

Two error kinds trigger it (same root cause)

consumer.py contains two patterns that pyrefly flags, both reported on lines with
no owning mutant:

  1. bad-argument-typeCORSMiddleware(app, **m.kwargs) (Starlette types
    Middleware.kwargs via a ParamSpec that pyrefly resolves to object here).
  2. bad-return — returning a nested dict from a function annotated
    Mapping[str, JsonValue].

Either one alone reproduces the crash; the underlying mutmut behavior is identical.

Why this is a mutmut issue, not a project issue

In the original project these patterns type-check cleanly in whole-project mode and
the crash appears only under mutmut's mutated tree — so the type errors are an
artifact of mutmut's rewrite/working-copy, not of the source. But even taking the
errors at face value: a do_not_mutate file by definition has no mutants, so a
type error there can never be attributed and will always crash mutmut. mutmut
should degrade gracefully instead of raising.

Suggested fix

In filter_mutants_with_type_checker, when no mutant owns a reported error:
skip/ignore it (optionally log it) rather than raising — at minimum for files that
contain no mutant methods (e.g. do_not_mutate files).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions