Skip to content

fix: SamSegmenter crashed on every run — checkpoint=None - #12

Merged
leiverkus merged 1 commit into
mainfrom
fix/sam-checkpoint-none
Jul 26, 2026
Merged

fix: SamSegmenter crashed on every run — checkpoint=None#12
leiverkus merged 1 commit into
mainfrom
fix/sam-checkpoint-none

Conversation

@leiverkus

Copy link
Copy Markdown
Owner

The SAM backend has never worked. Found by installing the sam extra locally for the first time.

The bug

SamSegmenter.segment passed checkpoint=self.checkpoint unconditionally. samgeo's constructor:

if "checkpoint" in kwargs:
    checkpoint = kwargs["checkpoint"]
    if not os.path.exists(checkpoint):   # ← None
        ...
else:
    checkpoint = download_checkpoint(model_type, checkpoint_dir, hq)

With the default checkpoint=None this takes the first branch and raises before a single mask is generated:

TypeError: stat: path should be string, bytes, os.PathLike or integer, not NoneType

Omitting the key entirely takes the else branch, which downloads the default weights for the model type — the intended behaviour.

Why it survived

tests/test_sam.py opens with pytest.importorskip("samgeo"), and CI installs neither the sam nor the cellpose extra. The only test covering this path has always skipped. v0.3.0 ships the backend as done, and nothing has exercised it since.

Where the regression test lives

In tests/test_make_segmenter.py, not beside the test it fixes. That module deliberately runs without the heavy dependencies — its existing test asserts that constructing the backends does not import samgeo/cellpose/torch. Putting the new test in test_sam.py would have made it skip in CI too, guarding nothing.

It asserts both directions: the key is absent when unset, and forwarded as a string when set.

A related gap, not fixed here

Installing the extras un-skips two tests that CI never runs. That is a standing blind spot rather than a one-off: any breakage in the SAM or Cellpose path is invisible until someone installs several GB of torch by hand. Worth deciding separately whether CI should carry that cost, or whether these backends need smoke tests that stub the heavy call.

Verification

ruff clean, mypy clean on 26 files, test_make_segmenter.py 4 passed in 0.01 s — with the extras absent, which is the condition CI runs under.

🤖 Generated with Claude Code

SamSegmenter passed `checkpoint=self.checkpoint` unconditionally. samgeo
runs `os.path.exists(checkpoint)` as soon as that key is present, so the
default `None` raised

  TypeError: stat: path should be string, bytes, os.PathLike or integer,
  not NoneType

before a single mask was generated. The SAM backend has therefore never
worked; omitting the key entirely makes samgeo download the default
weights for the model type, which is what was intended.

The bug survived because CI cannot see it. tests/test_sam.py opens with
`pytest.importorskip("samgeo")` and CI installs neither the sam nor the
cellpose extra, so the only test covering this path has always skipped.
It surfaced the moment the extras were installed locally.

The regression test therefore goes in tests/test_make_segmenter.py, which
deliberately runs without the heavy dependencies, rather than next to the
test it fixes — otherwise it would skip in CI too and guard nothing. It
asserts the key is absent when unset and forwarded as a string when set.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@leiverkus
leiverkus merged commit 424aa75 into main Jul 26, 2026
2 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