diff --git a/src/_zkapauthorizer/_plugin.py b/src/_zkapauthorizer/_plugin.py
index 1ec0f75305d2307cafeedd7187f08ef3e1779fa0..82d996f7c760bdee4ed6b72e0823ee43cb2b2050 100644
--- a/src/_zkapauthorizer/_plugin.py
+++ b/src/_zkapauthorizer/_plugin.py
@@ -238,7 +238,7 @@ def _create_maintenance_service(reactor, node_config, client_node):
     # Create the operation which performs the lease maintenance job when
     # called.
     maintain_leases = maintain_leases_from_root(
-        client_node.create_node_from_uri(
+        lambda: client_node.create_node_from_uri(
             node_config.get_private_config(b"rootcap"),
         ),
         client_node.get_storage_broker(),
diff --git a/src/_zkapauthorizer/lease_maintenance.py b/src/_zkapauthorizer/lease_maintenance.py
index f32de8dff441b6832a906f32681182c7a9233f45..4289232b0e3958ca097681f0388076633fa2836b 100644
--- a/src/_zkapauthorizer/lease_maintenance.py
+++ b/src/_zkapauthorizer/lease_maintenance.py
@@ -50,6 +50,7 @@ from twisted.python.log import (
 
 from allmydata.interfaces import (
     IDirectoryNode,
+    IFilesystemNode,
 )
 from allmydata.util.hashutil import (
     file_renewal_secret_hash,
@@ -81,6 +82,10 @@ def visit_storage_indexes(root_node, visit):
     :return Deferred: A Deferred which fires after all nodes have been
         visited.
     """
+    if not IFilesystemNode.providedBy(root_node):
+        raise TypeError("root_node must provide IFilesystemNode, {!r} does not".format(
+            root_node,
+        ))
     stack = [root_node]
     while stack:
         elem = stack.pop()
@@ -438,7 +443,7 @@ def read_time_from_path(path):
         return parse_datetime(when)
 
 
-def visit_storage_indexes_from_root(visitor, root_node):
+def visit_storage_indexes_from_root(visitor, get_root_node):
     """
     An operation for ``lease_maintenance_service`` which applies the given
     visitor to ``root_node`` and all its children.
@@ -446,14 +451,18 @@ def visit_storage_indexes_from_root(visitor, root_node):
     :param visitor: A one-argument callable which takes the traversal function
         and which should call it as desired.
 
-    :param IFilesystemNode root_node: The filesystem node at which traversal
-        will begin.
+    :param get_root_node: A no-argument callable which returns the filesystem
+        node (``IFilesystemNode``) at which traversal will begin.
 
     :return: A no-argument callable to perform the visits.
     """
-    return partial(
-        visitor,
-        partial(visit_storage_indexes, root_node),
+    return lambda: visitor(
+        partial(
+            visit_storage_indexes,
+            # Make sure we call get_root_node each time to give us a chance to
+            # notice when it changes.
+            get_root_node(),
+        ),
     )
 
 
@@ -486,7 +495,7 @@ class MemoryMaintenanceObserver(object):
 
 
 def maintain_leases_from_root(
-        root_node,
+        get_root_node,
         storage_broker,
         secret_holder,
         min_lease_remaining,
@@ -498,8 +507,9 @@ def maintain_leases_from_root(
     and all its children and renews their leases if they have
     ``min_lease_remaining`` or less on them.
 
-    :param IFilesystemNode root_node: A Tahoe-LAFS filesystem node to use as
-        the root of a node hierarchy to be maintained.
+    :param get_root_node: A no-argument callable which returns the Tahoe-LAFS
+        filesystem node (``IFilesystemNode``) to use as the root of a node
+        hierarchy to be maintained.
 
     :param StorageFarmBroker storage_broker: The storage broker which can put
         us in touch with storage servers where shares of the nodes to maintain
@@ -529,7 +539,7 @@ def maintain_leases_from_root(
 
     return visit_storage_indexes_from_root(
         visitor,
-        root_node,
+        get_root_node,
     )
 
 
diff --git a/src/_zkapauthorizer/tests/test_lease_maintenance.py b/src/_zkapauthorizer/tests/test_lease_maintenance.py
index 5b90fe3654839390e7a551bfc80b1d0a2bfd5160..d5dd7c530c81750a052ed9dfabf93dbd4e415f3d 100644
--- a/src/_zkapauthorizer/tests/test_lease_maintenance.py
+++ b/src/_zkapauthorizer/tests/test_lease_maintenance.py
@@ -411,7 +411,7 @@ class VisitStorageIndexesFromRootTests(TestCase):
 
         operation = visit_storage_indexes_from_root(
             perform_visit,
-            root_node,
+            lambda: root_node,
         )
 
         self.assertThat(
@@ -516,7 +516,7 @@ class MaintainLeasesFromRootTests(TestCase):
             )
 
         operation = maintain_leases_from_root(
-            root_node,
+            lambda: root_node,
             storage_broker,
             secret_holder,
             min_lease_remaining,
@@ -569,7 +569,7 @@ class MaintainLeasesFromRootTests(TestCase):
         observers = [observer]
         progress = observers.pop
         operation = maintain_leases_from_root(
-            root_node,
+            lambda: root_node,
             storage_broker,
             secret_holder,
             min_lease_remaining,
diff --git a/src/_zkapauthorizer/tests/test_plugin.py b/src/_zkapauthorizer/tests/test_plugin.py
index c6b4e89d0cff64d7870ae4588cdd2f1bc725bdd1..55c30a5d2205b5427300359c427f33c95482dca1 100644
--- a/src/_zkapauthorizer/tests/test_plugin.py
+++ b/src/_zkapauthorizer/tests/test_plugin.py
@@ -441,7 +441,7 @@ class LeaseMaintenanceServiceTests(TestCase):
     """
     Tests for the plugin's initialization of the lease maintenance service.
     """
-    def _created_test(self, get_config, servers_yaml):
+    def _created_test(self, get_config, servers_yaml, rootcap):
         original_tempdir = tempfile.tempdir
 
         tempdir = self.useFixture(TempDir())
@@ -455,10 +455,11 @@ class LeaseMaintenanceServiceTests(TestCase):
             b"servers.yaml",
             servers_yaml,
         )
-        config.write_private_config(
-            b"rootcap",
-            b"dddddddd",
-        )
+        if rootcap:
+            config.write_private_config(
+                b"rootcap",
+                b"dddddddd",
+            )
 
         try:
             d = create_client_from_config(config)
@@ -492,4 +493,19 @@ class LeaseMaintenanceServiceTests(TestCase):
         maintenance service after it has at least one storage server to
         connect to.
         """
-        return self._created_test(get_config, servers_yaml)
+        return self._created_test(get_config, servers_yaml, rootcap=True)
+
+
+    @settings(
+        deadline=None,
+    )
+    @given(
+        tahoe_configs_with_dummy_redeemer,
+        sampled_from([SERVERS_YAML, TWO_SERVERS_YAML]),
+    )
+    def test_created_without_rootcap(self, get_config, servers_yaml):
+        """
+        The lease maintenance service can be created even if no rootcap has yet
+        been written to the client's configuration directory.
+        """
+        return self._created_test(get_config, servers_yaml, rootcap=False)