From 1b012190dd8efb4cb70c9d7bd0be7e5ab18d6f7e Mon Sep 17 00:00:00 2001 From: Andrew Morgan Date: Wed, 24 Jun 2026 10:48:58 +0100 Subject: [PATCH 1/2] Move `JsonDict` import to type-checking path only I ran into the usual case where my `synapse_rust` module was outdated and needed to rebuild them before running the Complement tests. However, instead of getting the typical error of `Rust module outdated. Please rebuild using `poetry install`, I instead got the following: ``` COMPLEMENT_DIR="../complement" ./scripts-dev/complement.sh -run "TestMSC4429ProfileUpdates" Traceback (most recent call last): File "", line 1, in File "/home/work/code/synapse/synapse/util/__init__.py", line 41, in from synapse.types import JsonDict File "/home/work/code/synapse/synapse/types/__init__.py", line 70, in from synapse.synapse_rust.types import Requester ModuleNotFoundError: No module named 'synapse.synapse_rust.types'; 'synapse.synapse_rust' is not a package. ``` which is much more confusing for a irregular contributor to diagnose than the one that tells you to run `poetry install`. The cause was an edge case: I did not yet have the `synapse.synapse_rust.types` module, which was added only recently in https://github.com/element-hq/synapse/pull/19828. So you could argue this is a one-time hurdle. However, the need to import `synapse.synapse_rust.types` solely comes from needing to import `JsonDict`, which is only used for typechecking! Hence moving the import under `if typing.TYPE_CHECKING`. With this, I would have received the more noob-friendly error message instead of one about a `synapse_rust.types` module not existing. --- synapse/util/__init__.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/synapse/util/__init__.py b/synapse/util/__init__.py index 977a662d7a5..6b059c6b0e1 100644 --- a/synapse/util/__init__.py +++ b/synapse/util/__init__.py @@ -38,10 +38,8 @@ from twisted.internet import defer from twisted.python.failure import Failure -from synapse.types import JsonDict - if typing.TYPE_CHECKING: - pass + from synapse.types import JsonDict logger = logging.getLogger(__name__) @@ -189,7 +187,7 @@ def split_dict_to_fit_to_size( *, soft_max_size: int, wrapping_object_size: int = 2, -) -> Iterator[tuple[dict[str, JsonDict], int]]: +) -> Iterator[tuple[dict[str, "JsonDict"], int]]: """Splits a dict up into a list of dicts, each of which is small enough to fit into the given size when encoded as JSON. Every entry in the original dict is in exactly one of the resulting dicts. From e09c82de4c8dacc20db112b4dd89c433c3cca82b Mon Sep 17 00:00:00 2001 From: Andrew Morgan Date: Wed, 24 Jun 2026 10:52:21 +0100 Subject: [PATCH 2/2] newsfile --- changelog.d/19876.misc | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/19876.misc diff --git a/changelog.d/19876.misc b/changelog.d/19876.misc new file mode 100644 index 00000000000..694b5ddddee --- /dev/null +++ b/changelog.d/19876.misc @@ -0,0 +1 @@ +Prevent an obtuse error masking a more user-friendly error when trying to run Synapse with an outdated rust module in certain cases. \ No newline at end of file