Skip to content

Segmentation fault with Python 3.14.1, 3.13.10: insertdict: Assertion `!_PyDict_HasSplitTable(mp)' failed. #142218

Description

@emontnemery

Bug report

Bug description:

There's a segmentation fault in Python 3.14.1 and 3.13.10 which doesn't happen in the previous point releases.

I'm sorry about the messy reproducer, the issue was noticed in a much larger program and this is what I ended up with after removing all the cruft.

seg_fault_issue_import.py:

import asyncio
import atexit


class OtherClass:
    __slots__ = 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'

    def __init__(self):
        pass


def register_async_client_cleanup():

    def cleanup_wrapper():
        loop = asyncio.new_event_loop()
        loop.close()

    atexit.register(cleanup_wrapper)

register_async_client_cleanup()

seg_fault_debug.py:

from enum import StrEnum

from seg_fault_issue_import import OtherClass

class MyClass:

    def __init__(self):
        self.attr = OtherClass()


class MyEnum(StrEnum):
    ATTR = "attr"

mydata = MyClass()
setattr(mydata, MyEnum.ATTR, None)

Running seg_fault_debug.py causes a segmentation fault with Python 3.13.10 and 3.14.1:

$ python3 seg_fault_debug.py
Segmentation fault (core dumped)
Original reproducer

seg_fault_issue_import.py:

import asyncio
import atexit
from dataclasses import dataclass


@dataclass(slots=True)
class CPU:
    """CPU."""

    count: int | None = None
    frequency: float | None = None
    load_average: float | None = None
    per_cpu: list[float] | None = None
    power: float | None = None
    stats: float | None = None
    temperature: float | None = None
    times: float | None = None
    times_percent: float | None = None


def register_async_client_cleanup():

    def cleanup_wrapper():
        loop = asyncio.new_event_loop()
        loop.close()

    atexit.register(cleanup_wrapper)

register_async_client_cleanup()

seg_fault_debug.py:

from dataclasses import dataclass, field
from enum import StrEnum

from seg_fault_issue_import import CPU

@dataclass
class MyDataclass:

    attr: None = field(default_factory=CPU)


class MyEnum(StrEnum):
    ATTR = "attr"

mydata = MyDataclass()
setattr(mydata, MyEnum.ATTR, None)

CPython versions tested on:

3.14

Operating systems tested on:

Linux

Linked PRs

Activity

  1. johnslavik commented on Dec 3, 2025

    @johnslavik
    Member

    CC @ZeroIntensity (mentorship): type-crash, 3.14, 3.13, remove type-bug

    I'll try to reproduce

  2. johnslavik commented on Dec 3, 2025

    @johnslavik
    Member

    Triggers an assertion error in debug mode for 3.14, I assume the same for 3.13:

    ❯ ./python seg_fault_debug.py 
    python: Objects/dictobject.c:1866: insertdict: Assertion `!_PyDict_HasSplitTable(mp)' failed.
    Aborted (core dumped)
    

    I'll see if we can shrink the reproducer.

  3. added
    type-crashA hard crash of the interpreter, possibly with a core dump
    3.13only security fixes
    3.14bugs and security fixes
    3.15bugs and security fixes
    and removed
    type-bugAn unexpected behavior, bug, or error
    on Dec 3, 2025
  4. emontnemery commented on Dec 3, 2025

    @emontnemery
    ContributorAuthor

    I simplified the reproducer a little bit by removing the dataclasses, but it's still messy

  5. johnslavik commented on Dec 3, 2025

    @johnslavik
    Member

    This is related to the slow attribute resolution path -- can't reproduce with fast slot access, which is perhaps why the assertion error regards a dictionary insertion (__dict__).

  6. johnslavik commented on Dec 3, 2025

    @johnslavik
    Member

    Smaller, without dataclasses or asyncio:

    from enum import Enum
    
    class O:
        def __init__(self):
            self.attr = "whatever"
    
    class E(str, Enum):
        a = "attr"
    
    setattr(O(), E.a, "new-whatever")

    ("whatever" and "new-whatever" could be any other objects, e.g. None and an empty tuple)

  7. johnslavik commented on Dec 3, 2025

    @johnslavik
    Member

    Reproduced on 3.15, thanks @ZeroIntensity. This must have been a flawed bugfix backported everywhere.

  8. johnslavik commented on Dec 3, 2025

    @johnslavik
    Member
    from enum import Enum
    
    class O:
        def __init__(self):
            self.attr = "whatever"
    
    class E(str, Enum):
        a = "attr"
    
    O().__dict__.__setitem__(E.a, "something else")  # `E.a` as the string seems to cause segfault
  9. johnslavik commented on Dec 3, 2025

    @johnslavik
    Member

    The class is required in this repro -- I guess it's something related to how __dict__ is governed by the owner.

    For example, this will not fail:

    -O().__dict__.__setitem__(E.a, "something else")  # `E.a` as the string seems to cause segfault
    +import copy
    +copy.deepcopy(O().__dict__).__setitem__(E.a, "something else")

    So this likely isn't a problem with dictionaries.

  10. 7 remaining items

  11. changed the title [-]Segmentation fault with Python 3.14.1, 3.13.10[/-] [+]Segmentation fault with Python 3.14.1, 3.13.10: insertdict: Assertion `!_PyDict_HasSplitTable(mp)' failed.[/+] on Dec 3, 2025
  12. added 3 commits that reference this issue on Dec 3, 2025
  13. added a commit that references this issue on Dec 3, 2025
  14. added 3 commits that reference this issue on Dec 3, 2025
  15. hugovk commented on Dec 4, 2025

    @hugovk
    Member

    Thanks all for the quick report, repro minimising, bisecting, fixing, reviewing and backporting!

  16. added a commit that references this issue on Dec 6, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    3.13only security fixes3.14bugs and security fixes3.15bugs and security fixesinterpreter-core(Objects, Python, Grammar, and Parser dirs)release-blockertype-crashA hard crash of the interpreter, possibly with a core dump

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions