diff --git a/src/_zkapauthorizer/storage_common.py b/src/_zkapauthorizer/storage_common.py
index dd9a9f49e15bd542aa70cbbbdaadedfde5c64bbb..487c164aa7f5cce69a2e9a66d5cbbfaa475ecd4e 100644
--- a/src/_zkapauthorizer/storage_common.py
+++ b/src/_zkapauthorizer/storage_common.py
@@ -38,7 +38,7 @@ from pyutil.mathutil import (
     div_ceil,
 )
 
-@attr.s(frozen=True)
+@attr.s(frozen=True, str=True)
 class MorePassesRequired(Exception):
     """
     Storage operations fail with ``MorePassesRequired`` when they are not
@@ -50,11 +50,11 @@ class MorePassesRequired(Exception):
     ivar int required_count: The number of valid passes which must be
         presented for the operation to be authorized.
 
-    :ivar list[int] signature_check_failed: Indices into the supplied list of
+    :ivar set[int] signature_check_failed: Indices into the supplied list of
         passes indicating passes which failed the signature check.
     """
-    valid_count = attr.ib()
-    required_count = attr.ib()
+    valid_count = attr.ib(validator=attr.validators.instance_of((int, long)))
+    required_count = attr.ib(validator=attr.validators.instance_of((int, long)))
     signature_check_failed = attr.ib(converter=frozenset)
 
 
diff --git a/src/_zkapauthorizer/tests/test_storage_server.py b/src/_zkapauthorizer/tests/test_storage_server.py
index 1eddf1c2e2c173eda5ad4209c5a5397cf146dccb..314a0cf6ff21465769fcf3b73a8f4d456566e1c3 100644
--- a/src/_zkapauthorizer/tests/test_storage_server.py
+++ b/src/_zkapauthorizer/tests/test_storage_server.py
@@ -33,6 +33,8 @@ from testtools import (
 )
 from testtools.matchers import (
     Equals,
+    AfterPreprocessing,
+    MatchesAll,
 )
 from hypothesis import (
     given,
@@ -157,6 +159,36 @@ class ValidationResultTests(TestCase):
             ),
         )
 
+    def test_raise_for(self):
+        """
+        ``_ValidationResult.raise_for`` raises ``MorePassesRequired`` populated
+        with details of the validation and how it fell short of what was
+        required.
+        """
+        good = [0, 1, 2, 3]
+        badsig = [4]
+        required = 10
+        result = _ValidationResult(good, badsig)
+        try:
+            result.raise_for(required)
+        except MorePassesRequired as exc:
+            self.assertThat(
+                exc,
+                MatchesAll(
+                    Equals(
+                        MorePassesRequired(
+                            len(good),
+                            required,
+                            set(badsig),
+                        ),
+                    ),
+                    AfterPreprocessing(
+                        str,
+                        Equals("MorePassesRequired(valid_count=4, required_count=10, signature_check_failed=frozenset([4]))"),
+                    ),
+                ),
+            )
+
 
 class PassValidationTests(TestCase):
     """