FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

Python 3.14: __annotate__ NotImplementedError on annotated pytest fixtures, tests and pydantic models · Issue #1971 · microsoft/debugpy · GitHub

Repository navigation

Python 3.14: __annotate__ NotImplementedError on annotated pytest fixtures, tests and pydantic models #1971

Closed

Description

Didn't find this reported specifically, hence filing a new bug.
Not sure if it's debugger problem or pydantic / pytest / possibly others.

Environment data

  • debugpy version: 1.8.16 baked in ms-python.debugpy-2025.15.2025110302-linux-x64
  • OS and version: Fedora 42 kernel 6.17.5-200.fc42.x86_64
  • Python version (& distribution if applicable, e.g. Anaconda): Python 3.14.0 (main, Oct 7 2025, 00:00:00) [GCC 15.2.1 20250808 (Red Hat 15.2.1-1)] on linux
  • Using VS Code or Visual Studio:
    VS Code
    Version: 1.105.1
    Commit: 7d842fb85a0275a4a8e4d7e040d2625abbf7f084
    Date: 2025-10-14T22:33:36.618Z
    Electron: 37.6.0
    ElectronBuildId: 12502201
    Chromium: 138.0.7204.251
    Node.js: 22.19.0
    V8: 13.8.258.32-electron.0
    OS: Linux x64 6.17.5-200.fc42.x86_64

Actual behavior

Debugger raises "User Uncaught Exceptions" on every annotated pytest fixture and pydantic model on python 3.14 when they're imported (I guess it tries to inspect annotations in wrong way or these libraries are somehow mangling the new annotations).
On python 3.13 - it works fine (no exceptions).

Exception has occurred: NotImplementedError       (note: full exception trace is shown but execution is paused at: __annotate__)
exception: no description
  File "/home/pslama/wrkspaces/test/test_annotations.py", line 25, in __annotate__ (Current frame)
    class AnnotatedTest(BaseModel):
    
  File "/home/pslama/wrkspaces/test/test_annotations.py", line 25, in <module>
    class AnnotatedTest(BaseModel):
NotImplementedError: 

Expected behavior

No such exceptions.

Steps to reproduce:

  1. Create py3.14 venv with pydantic and pytest packages
  2. Configure pytest as test runner in VS Code test explorer
  3. Create test_anything.py file containing pydantic model and/or annotated pytest fixture and test function
  4. Check User Uncaught Exceptions in Run and Debug panel
  5. Run Debug Tests from test explorer

I made example repo: https://github.com/pavel-slama/py3.14-annotate-test

Activity

  1. rchiodo commented on Nov 4, 2025

    Contributor

    I believe this is caused by justMyCode not working entirely in 3.14. If you turn off 'User Uncaught Exceptions' or you ignore the exception, the test passes. pytest is throwing an exception and debugpy is marking that exception as being thrown from user code (which is where the bug is). But the exception is harmless.

  2. rchiodo commented on Nov 4, 2025

    Contributor

    Looking at the __annotate__ stack, it looks like debugpy would have to special case this. This is where 3.14 is calling the annotate function:

    def call_annotate_function(annotate, format, *, owner=None, _is_evaluate=False):
        """Call an __annotate__ function. __annotate__ functions are normally
        generated by the compiler to defer the evaluation of annotations. They
        can be called with any of the format arguments in the Format enum, but
        compiler-generated __annotate__ functions only support the VALUE format.
        This function provides additional functionality to call __annotate__
        functions with the FORWARDREF and STRING formats.
    
        *annotate* must be an __annotate__ function, which takes a single argument
        and returns a dict of annotations.
    
        *format* must be a member of the Format enum or one of the corresponding
        integer values.
    
        *owner* can be the object that owns the annotations (i.e., the module,
        class, or function that the __annotate__ function derives from). With the
        FORWARDREF format, it is used to provide better evaluation capabilities
        on the generated ForwardRef objects.
    
        """
        if format == Format.VALUE_WITH_FAKE_GLOBALS:
            raise ValueError("The VALUE_WITH_FAKE_GLOBALS format is for internal use only")
        try:
            return annotate(format) <-- this line here
        except NotImplementedError:

    I think it was caused by a change in 3.14 here:
    python/cpython@7b7b90d

  3. pavel-slama commented on Nov 4, 2025

    Author

    I believe this is caused by justMyCode not working entirely in 3.14. If you turn off 'User Uncaught Exceptions' or you ignore the exception, the test passes. pytest is throwing an exception and debugpy is marking that exception as being thrown from user code (which is where the bug is). But the exception is harmless.

    I know the exceptions can be ignored and the test passes, but so many exceptions (one for each annotated model, fixture, test) despite being harmless render whole "User Uncaught Exceptions" unusable in 3.14.

    But without it the debugger won't stop even on geniune exceptions raised in user code during pytest run - and that's a problem during test debugging.

  4. changed the title [-]Python 3.14: __annotate__ NotImplementedError on annotated pytest fixtures / pydantic models[/-] [+]Python 3.14: __annotate__ NotImplementedError on annotated pytest fixtures, tests and pydantic models[/+] on Nov 4, 2025
  5. brettcannon commented on Nov 4, 2025

    Member

    In 3.14 the way annotations work by default changed. They are now effectively closures/thunks to make the evaluation of the annotations lazy. As such, when you try to read them they need to be resolved (typically with annotationslib), which then means executing the closure. I think debugpy just needs to be taught that those closures are a Python thing and not a user thing.

  6. tiborrr commented on Dec 15, 2025

    Pavel Slama (@pavel-slama) as a workaround you can add the #@IgnoreException to your code:

    for example:

    class SelectOption(BaseModel, frozen=True): #@IgnoreException
        """Model for select option."""
    
        value: str
        text: str
        selected: bool = False
  7. pavel-slama commented on Dec 16, 2025

    Author

    Tibor (@tiborrr) I know, but it means adding the ignore to every pydantic model, every pytest fixture and every test! That's a lot of clutter for a workaround.

    I'm sticking to py3.13 until it's fixed.

  8. rollokd commented on Jan 9, 2026

    +1

    I found the same issue using pydantic and pytest in our codebase, installed with uv and running in cursor.

  9. rollokd commented on Jan 19, 2026

    Rich Chiodo (@rchiodo) I'm not sure who best to ask but is it possible to accelerate the next release to get this out? It is making debugging in Cursor and Vscode almost unusable

  10. flying-sheep commented on Jan 19, 2026

    Rollo Kennedy-Dyson (@rollokd) I’m all for it but can’t you just debug on Python 3.13?

  11. rchiodo commented on Jan 20, 2026

    Contributor

    I usually wait until there's a least 2 or 3 fixes before releasing. Maybe this one is important enough to warrant its own fix though.

  12. rchiodo commented on Jan 21, 2026

    Contributor

    This is going to be a while. There are bugs in our build pipeline that depend upon another team fixing their output. Debugpy binaries have to run through a bunch of security checks and we're stalled waiting on the C++ compiler to fix a warning in a lib.

  13. rollokd commented on Jan 21, 2026

    Philipp A. (@flying-sheep) maybe I am missing something but it's a pain to keep deleting and reinstalling my environment when swapping from 3.14 for production and 3.13 for debugging as writing code in 3.13 and then pushing to 3.14 seems like a recipe for disaster.
    Rich Chiodo (@rchiodo) I appreciate you trying, hopefully these other pipeline issues and patches get sorted soon.

  14. pavel-slama commented on Jan 21, 2026

    Author

    @flying-sheep maybe I am missing something but it's a pain to keep deleting and reinstalling my environment when swapping from 3.14 for production and 3.13 for debugging as writing code in 3.13 and then pushing to 3.14 seems like a recipe for disaster.

    Rollo Kennedy-Dyson (@rollokd) I don't know your setup but you can create 2 environments (like .venv3.13 and .venv3.14) and switch in python environments extension (+deactivate and reactivate environment in open terminals - there's a button to do that). And then keep them both up to date whenever dependecies change. Somewhat cumbersome but at least locally works. With containers it's worse - those you'd have to keep rebuilding..

  15. flying-sheep commented on Jan 21, 2026

    We’re getting far off-topic here, but this is exactly why I use Hatch instead of uv’s CLI. With Hatch one declares multiple environments for multiple test scenarios, and you can easily run stuff in them like e.g. hatch run hatch-test.py3.14:uv pip list. In our projects, we usually use three test environments: “default resolution with all extras with newest Python” (should give what users installing the package get), “minimal specified version with all extras and minimum supported Python”, and “default, but no extras active” (to check if no misplaced imports introduce accidental dependencies).

  16. rchiodo commented on Jan 29, 2026

    Contributor

    Version https://github.com/microsoft/debugpy/releases/tag/v1.8.20 has the fix for this issue. It should show up in a future version of the vscode-python-debugger extension or you can install it through pypi.

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

Metadata

Metadata

Labels

Fixed in next releaseThis issue has been fixed, but won't be available to customers until the next release.

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions


    Back | FazBrowse Home | New Git URL