Skip to content

dbm.sqlite3 setdefault() fails due to NOT NULL constraint preventing None values #137886

@furkanonder

Description

@furkanonder

Bug report

Bug description:

dbm.sqlite3 fails with "NOT NULL constraint failed: Dict.value" when trying to store None values, breaking compatibility with dict interface and other DBM backends. This particularly affects the setdefault() method which should default to None when called with a single argument.

Expected Behavior

According to dbm documentation:

"The object returned by open() supports the same basic functionality as a dict; keys and their corresponding values can be stored, retrieved, and deleted, and the in operator and the keys() method are available, as well as get() and setdefault() methods."

Actual Behavior

import dbm.sqlite3
import tempfile

d = {}
result = d.setdefault('missing')
print(d['missing'])

with tempfile.NamedTemporaryFile() as tmp:
    db = dbm.sqlite3.open(tmp.name, 'c')
    result = db.setdefault('missing_key')
    db.close()

Output:

None
Traceback (most recent call last):
  File "<frozen _collections_abc>", line 1000, in setdefault
  File "/usr/lib/python3.13/dbm/sqlite3.py", line 92, in __getitem__
    raise KeyError(key)
KeyError: 'missing_key'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/lib/python3.13/dbm/sqlite3.py", line 79, in _execute
    return closing(self._cx.execute(*args, **kwargs))
                   ~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^
sqlite3.IntegrityError: NOT NULL constraint failed: Dict.value

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/arf/repro.py", line 10, in <module>
    result = db.setdefault('missing_key')
  File "<frozen _collections_abc>", line 1002, in setdefault
  File "/usr/lib/python3.13/dbm/sqlite3.py", line 96, in __setitem__
    self._execute(STORE_KV, (key, value))
    ~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.13/dbm/sqlite3.py", line 81, in _execute
    raise error(str(exc))
dbm.sqlite3.error: NOT NULL constraint failed: Dict.value

There is no issue when a default argument is explicitly provided to setdefault.

import dbm.sqlite3
import tempfile

with tempfile.NamedTemporaryFile() as tmp:
    db = dbm.sqlite3.open(tmp.name, 'c')
    result = db.setdefault('missing_key', "default")
    print(result)
    db.close()

This behavior has also been reported for dbm.gnu and dbm.dumb objects in issue #77566.

CPython versions tested on:

CPython main branch, 3.14, 3.15, 3.13

Operating systems tested on:

Linux

Metadata

Metadata

Assignees

No one assigned

    Labels

    3.13bugs and security fixes3.14bugs and security fixes3.15new features, bugs and security fixesstdlibPython modules in the Lib dirtype-bugAn unexpected behavior, bug, or error

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions