diff --git a/docs/source/contributing.rst b/docs/source/contributing.rst
index abb480b8..3b0efb6d 100644
--- a/docs/source/contributing.rst
+++ b/docs/source/contributing.rst
@@ -309,8 +309,7 @@ Release notes
 ~~~~~~~~~~~~~
 
 We use `towncrier <https://github.com/hawkowl/towncrier>`__ to manage
-our `release notes <https://trio.readthedocs.io/en/latest/history.html>`__.
-Basically, every pull request that has a user
+our release notes. Basically, every pull request that has a user
 visible effect should add a short file to the ``newsfragments/``
 directory describing the change, with a name like ``<ISSUE
 NUMBER>.<TYPE>.rst``. See `newsfragments/README.rst
diff --git a/newsfragments/674.misc.rst b/newsfragments/674.misc.rst
new file mode 100644
index 00000000..9895259c
--- /dev/null
+++ b/newsfragments/674.misc.rst
@@ -0,0 +1,1 @@
+Calling ``str`` on a :exc:`trio.Cancelled` exception object returns "Cancelled" instead of an empty string.
\ No newline at end of file
diff --git a/trio/_core/_exceptions.py b/trio/_core/_exceptions.py
index 6b4302e3..dac864cb 100644
--- a/trio/_core/_exceptions.py
+++ b/trio/_core/_exceptions.py
@@ -73,6 +73,9 @@ class Cancelled(BaseException):
             )
         super().__init__()
 
+    def __str__(self):
+        return "Cancelled"
+
     @classmethod
     def _init(cls):
         """A private constructor so that a user-created instance of Cancelled

trio.Cancelled missing readable str()
Trying to print a trio.Cancelled exception e.g. with `f'{exc}'` yields an empty string.  I usually resort to `type(exc)` when I need to see what's going on.
diff --git a/trio/_core/tests/test_run.py b/trio/_core/tests/test_run.py
index 5b93ce82..b1586f3e 100644
--- a/trio/_core/tests/test_run.py
+++ b/trio/_core/tests/test_run.py
@@ -2070,6 +2070,11 @@ def test_Cancelled_init():
     _core.Cancelled._init()
 
 
+def test_Cancelled_str():
+    cancelled = _core.Cancelled._init()
+    assert str(cancelled) == 'Cancelled'
+
+
 def test_sniffio_integration():
     with pytest.raises(sniffio.AsyncLibraryNotFoundError):
         sniffio.current_async_library()

pip install -e .[dev]
parse_log_pytest
pytest
pytest pytest-cov pytest-faulthandler
3.9
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
async-generator==1.10
attrs==25.3.0
coverage==7.8.0
exceptiongroup @ file:///croot/exceptiongroup_1706031385326/work
idna==3.10
iniconfig @ file:///home/linux1/recipes/ci/iniconfig_1610983019677/work
outcome==1.3.0.post0
packaging @ file:///croot/packaging_1734472117206/work
pluggy @ file:///croot/pluggy_1733169602837/work
pytest @ file:///croot/pytest_1738938843180/work
pytest-cov==6.0.0
pytest-faulthandler==2.0.1
sniffio==1.3.1
sortedcontainers==2.4.0
tomli @ file:///opt/conda/conda-bld/tomli_1657175507142/work
-e git+https://github.com/python-trio/trio.git@b117c019a5c20e604c8429ea0b8fa1d395b50e36#egg=trio

name: trio
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - exceptiongroup=1.2.0=py39h06a4308_0
  - iniconfig=1.1.1=pyhd3eb1b0_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=3.0.16=h5eee18b_0
  - packaging=24.2=py39h06a4308_0
  - pip=25.0=py39h06a4308_0
  - pluggy=1.5.0=py39h06a4308_0
  - pytest=8.3.4=py39h06a4308_0
  - python=3.9.21=he870216_1
  - readline=8.2=h5eee18b_0
  - setuptools=75.8.0=py39h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - tomli=2.0.1=py39h06a4308_0
  - tzdata=2025a=h04d1e81_0
  - wheel=0.45.1=py39h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - async-generator==1.10
      - attrs==25.3.0
      - coverage==7.8.0
      - idna==3.10
      - outcome==1.3.0.post0
      - pytest-cov==6.0.0
      - pytest-faulthandler==2.0.1
      - sniffio==1.3.1
      - sortedcontainers==2.4.0
      - trio==0.11.0+dev
prefix: /opt/conda/envs/trio

trio/_core/tests/test_run.py::test_Cancelled_str
trio/_core/tests/test_run.py::test_instruments_crash trio/_core/tests/test_run.py::test_broken_abort trio/_core/tests/test_run.py::test_error_in_run_loop
trio/_core/tests/test_run.py::test_basic trio/_core/tests/test_run.py::test_initial_task_error trio/_core/tests/test_run.py::test_run_nesting trio/_core/tests/test_run.py::test_nursery_warn_use_async_with trio/_core/tests/test_run.py::test_nursery_main_block_error_basic trio/_core/tests/test_run.py::test_child_crash_basic trio/_core/tests/test_run.py::test_basic_interleave trio/_core/tests/test_run.py::test_task_crash_propagation trio/_core/tests/test_run.py::test_main_and_task_both_crash trio/_core/tests/test_run.py::test_two_child_crashes trio/_core/tests/test_run.py::test_child_crash_wakes_parent trio/_core/tests/test_run.py::test_reschedule trio/_core/tests/test_run.py::test_current_time trio/_core/tests/test_run.py::test_current_time_with_mock_clock trio/_core/tests/test_run.py::test_current_clock trio/_core/tests/test_run.py::test_current_task trio/_core/tests/test_run.py::test_root_task trio/_core/tests/test_run.py::test_out_of_context trio/_core/tests/test_run.py::test_current_statistics trio/_core/tests/test_run.py::test_instruments trio/_core/tests/test_run.py::test_instruments_interleave trio/_core/tests/test_run.py::test_null_instrument trio/_core/tests/test_run.py::test_instrument_before_after_run trio/_core/tests/test_run.py::test_instrument_task_spawn_exit trio/_core/tests/test_run.py::test_cancel_scope_repr trio/_core/tests/test_run.py::test_cancel_points trio/_core/tests/test_run.py::test_cancel_edge_cases trio/_core/tests/test_run.py::test_cancel_scope_multierror_filtering trio/_core/tests/test_run.py::test_precancelled_task trio/_core/tests/test_run.py::test_cancel_shielding trio/_core/tests/test_run.py::test_cancel_inheritance trio/_core/tests/test_run.py::test_cancel_shield_abort trio/_core/tests/test_run.py::test_basic_timeout trio/_core/tests/test_run.py::test_cancel_scope_deprecated trio/_core/tests/test_run.py::test_cancel_scope_nesting trio/_core/tests/test_run.py::test_cancel_unbound trio/_core/tests/test_run.py::test_timekeeping trio/_core/tests/test_run.py::test_failed_abort trio/_core/tests/test_run.py::test_spawn_system_task trio/_core/tests/test_run.py::test_system_task_crash trio/_core/tests/test_run.py::test_system_task_crash_MultiError trio/_core/tests/test_run.py::test_system_task_crash_plus_Cancelled trio/_core/tests/test_run.py::test_system_task_crash_KeyboardInterrupt trio/_core/tests/test_run.py::test_yield_briefly_checks_for_timeout trio/_core/tests/test_run.py::test_exc_info trio/_core/tests/test_run.py::test_exc_info_after_yield_error trio/_core/tests/test_run.py::test_exception_chaining_after_yield_error trio/_core/tests/test_run.py::test_nursery_exception_chaining_doesnt_make_context_loops trio/_core/tests/test_run.py::test_TrioToken_identity trio/_core/tests/test_run.py::test_TrioToken_run_sync_soon_basic trio/_core/tests/test_run.py::test_TrioToken_run_sync_soon_too_late trio/_core/tests/test_run.py::test_TrioToken_run_sync_soon_idempotent trio/_core/tests/test_run.py::test_TrioToken_run_sync_soon_idempotent_requeue trio/_core/tests/test_run.py::test_TrioToken_run_sync_soon_after_main_crash trio/_core/tests/test_run.py::test_TrioToken_run_sync_soon_crashes trio/_core/tests/test_run.py::test_TrioToken_run_sync_soon_FIFO trio/_core/tests/test_run.py::test_TrioToken_run_sync_soon_starvation_resistance trio/_core/tests/test_run.py::test_TrioToken_run_sync_soon_threaded_stress_test trio/_core/tests/test_run.py::test_TrioToken_run_sync_soon_massive_queue trio/_core/tests/test_run.py::test_slow_abort_basic trio/_core/tests/test_run.py::test_slow_abort_edge_cases trio/_core/tests/test_run.py::test_task_tree_introspection trio/_core/tests/test_run.py::test_nursery_closure trio/_core/tests/test_run.py::test_spawn_name trio/_core/tests/test_run.py::test_current_effective_deadline trio/_core/tests/test_run.py::test_nice_error_on_bad_calls_to_run_or_spawn trio/_core/tests/test_run.py::test_calling_asyncio_function_gives_nice_error trio/_core/tests/test_run.py::test_trivial_yields trio/_core/tests/test_run.py::test_nursery_start trio/_core/tests/test_run.py::test_task_nursery_stack trio/_core/tests/test_run.py::test_nursery_start_with_cancelled_nursery trio/_core/tests/test_run.py::test_nursery_start_keeps_nursery_open trio/_core/tests/test_run.py::test_nursery_explicit_exception trio/_core/tests/test_run.py::test_nursery_stop_iteration trio/_core/tests/test_run.py::test_nursery_stop_async_iteration trio/_core/tests/test_run.py::test_traceback_frame_removal trio/_core/tests/test_run.py::test_contextvar_support trio/_core/tests/test_run.py::test_contextvar_multitask trio/_core/tests/test_run.py::test_system_task_contexts trio/_core/tests/test_run.py::test_Cancelled_init trio/_core/tests/test_run.py::test_sniffio_integration trio/_core/tests/test_run.py::test_Task_custom_sleep_data trio/_core/tests/test_run.py::test_permanently_detach_coroutine_object trio/_core/tests/test_run.py::test_detach_and_reattach_coroutine_object trio/_core/tests/test_run.py::test_detached_coroutine_cancellation
trio/_core/_exceptions.py newsfragments/674.misc.rst docs/source/contributing.rst
trio/_core/_exceptions.py newsfragments/674.misc.rst docs/source/contributing.rst