diff --git a/mercurial/formatter.py b/mercurial/formatter.py
index f1c54d0033272bba950eb86c63c2896def29270a_bWVyY3VyaWFsL2Zvcm1hdHRlci5weQ==..a33be093ec62458599582687540842b15839b121_bWVyY3VyaWFsL2Zvcm1hdHRlci5weQ== 100644
--- a/mercurial/formatter.py
+++ b/mercurial/formatter.py
@@ -94,10 +94,10 @@
 
 >>> def subrepos(ui, fm):
 ...     fm.startitem()
-...     fm.write(b'repo', b'[%s]\\n', b'baz')
+...     fm.write(b'reponame', b'[%s]\\n', b'baz')
 ...     files(ui, fm.nested(b'files'))
 ...     fm.end()
 >>> show(subrepos)
 [baz]
 foo
 bar
@@ -98,10 +98,10 @@
 ...     files(ui, fm.nested(b'files'))
 ...     fm.end()
 >>> show(subrepos)
 [baz]
 foo
 bar
->>> show(subrepos, template=b'{repo}: {join(files % "{path}", ", ")}\\n')
+>>> show(subrepos, template=b'{reponame}: {join(files % "{path}", ", ")}\\n')
 baz: foo, bar
 """
 
@@ -491,4 +491,5 @@
     and function"""
     return {
         'cache': {},  # for templatekw/funcs to store reusable data
+        'ctx': None,
         'repo': repo,
@@ -494,4 +495,5 @@
         'repo': repo,
+        'revcache': None,  # per-ctx cache; set later
         'ui': ui,
     }
 
diff --git a/mercurial/templater.py b/mercurial/templater.py
index f1c54d0033272bba950eb86c63c2896def29270a_bWVyY3VyaWFsL3RlbXBsYXRlci5weQ==..a33be093ec62458599582687540842b15839b121_bWVyY3VyaWFsL3RlbXBsYXRlci5weQ== 100644
--- a/mercurial/templater.py
+++ b/mercurial/templater.py
@@ -1320,7 +1320,9 @@
 
     def symbol(self, mapping, key):
         """Resolve symbol to value or function; None if nothing found"""
-        v = mapping.get(key)
+        v = None
+        if key not in self._resources:
+            v = mapping.get(key)
         if v is None:
             v = self._defaults.get(key)
         return v
@@ -1328,7 +1330,9 @@
     def resource(self, mapping, key):
         """Return internal data (e.g. cache) used for keyword/function
         evaluation"""
-        v = mapping.get(key)
+        v = None
+        if key in self._resources:
+            v = mapping.get(key)
         if v is None:
             v = self._resources.get(key)
         if v is None:
@@ -1332,7 +1336,7 @@
         if v is None:
             v = self._resources.get(key)
         if v is None:
-            raise KeyError
+            raise error.Abort(_('template resource not available: %s') % key)
         return v
 
     def _load(self, t):
diff --git a/tests/test-command-template.t b/tests/test-command-template.t
index f1c54d0033272bba950eb86c63c2896def29270a_dGVzdHMvdGVzdC1jb21tYW5kLXRlbXBsYXRlLnQ=..a33be093ec62458599582687540842b15839b121_dGVzdHMvdGVzdC1jb21tYW5kLXRlbXBsYXRlLnQ= 100644
--- a/tests/test-command-template.t
+++ b/tests/test-command-template.t
@@ -206,7 +206,13 @@
 
 Internal resources shouldn't be exposed (issue5699):
 
-  $ hg log -r. -T '{cache}{repo}{templ}{ui}'
+  $ hg log -r. -T '{cache}{ctx}{repo}{revcache}{templ}{ui}'
+
+Never crash on internal resource not available:
+
+  $ hg --cwd .. debugtemplate '{"c0bebeef"|shortest}\n'
+  abort: template resource not available: ctx
+  [255]
 
 Quoting for ui.logtemplate