Skip to content

bool values are stored as Int instead of Boolean #25

@machielg

Description

@machielg

Summary

Boolean values written to a document round-trip back as int because the type-inference dispatch in _infer_scalar_type checks int before bool, and bool is a subclass of int in Python — so True and False always match the int branch
first and are stored as Int.

Reproduction

from automerge import Document

doc = Document()
with doc.change() as d:
    d["flag"] = True

value = doc["flag"]
print(type(value), value)
# actual:   <class 'int'> 1
# expected: <class 'bool'> True

Code reference

src/automerge/document.py:555-569_infer_scalar_type:

def _infer_scalar_type(value: core.ScalarValue) -> core.ScalarType:
    if isinstance(value, str):
        return core.ScalarType.Str
    elif isinstance(value, bytes):
        return core.ScalarType.Bytes
    elif isinstance(value, int):          # matches True/False first
        return core.ScalarType.Int
    elif isinstance(value, float):
        return core.ScalarType.F64
    elif isinstance(value, bool):         # unreachable
        return core.ScalarType.Boolean
    ...

Impact

Any document that stores booleans loses type information at the Python boundary. Downstream code doing if doc["flag"] is True or type(doc["flag"]) is bool silently breaks. Sync-protocol interop with JS/Rust peers that write Boolean scalars is
unaffected on read, but new writes from Python end up as Int.

Environment

Reproduced on main at f72374e.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions