Skip to content

Introduce ExitCode.COLLECTION_ERROR for collection errors - #15012

Open
SemTiOne wants to merge 5 commits into
pytest-dev:mainfrom
SemTiOne:fix/4603-collection-error-exit-code
Open

Introduce ExitCode.COLLECTION_ERROR for collection errors#15012
SemTiOne wants to merge 5 commits into
pytest-dev:mainfrom
SemTiOne:fix/4603-collection-error-exit-code

Conversation

@SemTiOne

Copy link
Copy Markdown
Contributor

Closes #4603

Previously collection errors exited 2, they now exit 7 (ExitCode.COLLECTION_ERROR).

  • Include documentation when adding new features.
  • Include new tests or update existing tests when applicable.
  • Allow maintainers to push and squash when merging my commits. Please uncheck this if you prefer to squash the commits yourself.
  • Add text like closes #XYZW to the PR description and/or commits (where XYZW is the issue number). See the github docs for more information.
  • If AI agents were used, they are credited in Co-authored-by commit trailers.
  • Create a new changelog file in the changelog directory, with a name like <ISSUE NUMBER>.<TYPE>.rst. See changelog/README.rst for details.
  • Add yourself to AUTHORS in alphabetical order.

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
@psf-chronographer psf-chronographer Bot added the bot:chronographer:provided (automation) changelog entry is part of PR label Sep 13, 2026

@RonnyPfannschmidt RonnyPfannschmidt left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like it

We may need to assess if this is breaking for some people

Comment thread src/_pytest/main.py
@RonnyPfannschmidt

Copy link
Copy Markdown
Member

ci fixed needed

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
@SemTiOne SemTiOne changed the title [WIP] Introduce ExitCode.COLLECTION_ERROR for collection errors Introduce ExitCode.COLLECTION_ERROR for collection errors Sep 13, 2026
@SemTiOne
SemTiOne marked this pull request as ready for review September 13, 2026 13:17

@Pierre-Sassoulas Pierre-Sassoulas left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. More tests changed than code is a good sign.

@RonnyPfannschmidt

Copy link
Copy Markdown
Member

please investigate what triggered the rtd failure

@SemTiOne

Copy link
Copy Markdown
Contributor Author

GTG.

@bluetech bluetech left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. I left a few comments but nothing to change really.

Comment thread src/_pytest/main.py
@@ -399,7 +401,7 @@ def pytest_collection(session: Session) -> None:

def pytest_runtestloop(session: Session) -> bool:
if session.testsfailed and not session.config.option.continue_on_collection_errors:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Preexisting) I'm curious why this check happens in pytest_runtestloop instead of pytest_collection. To me it makes more sense as part of the collection phase, instead of runtest phase needing to check for "leftovers" from collection.

Comment thread src/_pytest/main.py
Comment on lines +528 to +529
Subclasses ``Interrupted`` for compatibility; ``wrap_session`` maps it
to ``ExitCode.COLLECTION_ERROR``.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO a lower level shouldn't refer to what a higher level does with it. It can easily become outdated.

Suggested change
Subclasses ``Interrupted`` for compatibility; ``wrap_session`` maps it
to ``ExitCode.COLLECTION_ERROR``.
Subclasses ``Interrupted`` for compatibility.

Comment thread testing/python/collect.py
"",
"test_collect_error_with_fulltrace.py:1: AssertionError",
"*! Interrupted: 1 error during collection !*",
"*! CollectionInterrupted: 1 error during collection !*",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks a bit ugly to me, in the sense that as a user it would look to me like pytest's implementation leaks into the user interface. Interrupted is less jarring because it's a proper word. Though I guess KeyboardInterrupt is the same. So it's fine.

An alternative is to avoid a separate CollectionInterrupted exception and use a parameter to Interrupted instead. But I figure you intentionally separated the two, since "interrupted" is really not a good fit for collection errors, but have to do it for backward compat.

Comment thread src/_pytest/main.py
exitstatus: int | ExitCode = ExitCode.INTERRUPTED
if isinstance(excinfo.value, CollectionInterrupted):
exitstatus = ExitCode.COLLECTION_ERROR
if isinstance(excinfo.value, exit.Exception):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if isinstance(excinfo.value, exit.Exception):
elif isinstance(excinfo.value, exit.Exception):

Comment thread src/_pytest/terminal.py
if session.shouldfail:
self.write_sep("!", str(session.shouldfail), red=True)
if exitstatus == ExitCode.INTERRUPTED:
if exitstatus in (ExitCode.INTERRUPTED, ExitCode.COLLECTION_ERROR):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Preexisting) I wonder why we have _report_keyboardinterrupt both in pytest_sessionfinish and in pytest_unconfigure. Probably there's a good reason, I wish there was a code comment for it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bot:chronographer:provided (automation) changelog entry is part of PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Syntax error in test file makes pytest exit with exit code 2

4 participants