diff --git a/CHANGES.rst b/CHANGES.rst
index d9ecaf643..fcd77f56b 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -18,6 +18,9 @@ https://github.com/zopefoundation/Zope/blob/4.x/CHANGES.rst
 - Added image dimensions to SVG file properties
   `#1146 <https://github.com/zopefoundation/Zope/pull/1146>`_.
 
+- Fix username not in access log for error requests, see issue
+  `#1155 <https://github.com/zopefoundation/Zope/issues/1155>`_.
+
 5.8.4 (2023-09-06)
 ------------------
 
diff --git a/src/ZPublisher/WSGIPublisher.py b/src/ZPublisher/WSGIPublisher.py
index 8f992587b..af66908f6 100644
--- a/src/ZPublisher/WSGIPublisher.py
+++ b/src/ZPublisher/WSGIPublisher.py
@@ -387,12 +387,13 @@ def publish_module(environ, start_response,
             try:
                 with load_app(module_info) as new_mod_info:
                     with transaction_pubevents(request, response):
-                        response = _publish(request, new_mod_info)
-
-                        user = getSecurityManager().getUser()
-                        if user is not None and \
-                           user.getUserName() != 'Anonymous User':
-                            environ['REMOTE_USER'] = user.getUserName()
+                        try:
+                            response = _publish(request, new_mod_info)
+                        finally:
+                            user = getSecurityManager().getUser()
+                            if user is not None and \
+                               user.getUserName() != 'Anonymous User':
+                                environ['REMOTE_USER'] = user.getUserName()
                 break
             except TransientError:
                 if request.supports_retry():

diff --git a/src/ZPublisher/tests/test_WSGIPublisher.py b/src/ZPublisher/tests/test_WSGIPublisher.py
index 88c29ba0b..b624a3ac7 100644
--- a/src/ZPublisher/tests/test_WSGIPublisher.py
+++ b/src/ZPublisher/tests/test_WSGIPublisher.py
@@ -820,6 +820,15 @@ class TestPublishModule(ZopeTestCase):
         self._callFUT(environ, start_response, _publish)
         self.assertFalse('REMOTE_USER' in environ)
 
+    def test_set_REMOTE_USER_environ_error(self):
+        environ = self._makeEnviron()
+        start_response = DummyCallable()
+        _publish = DummyCallable()
+        _publish._raise = ValueError()
+        with self.assertRaises(ValueError):
+            self._callFUT(environ, start_response, _publish)
+        self.assertEqual(environ['REMOTE_USER'], user_name)
+
     def test_webdav_source_port(self):
         from ZPublisher import WSGIPublisher
         old_webdav_source_port = WSGIPublisher._WEBDAV_SOURCE_PORT

Username not in access log for error requests
## BUG/PROBLEM REPORT / FEATURE REQUEST

<!--

Please do not report security-related issues here. Report them by email to security@plone.org. The Security Team will contact the relevant maintainer if necessary.

Include tracebacks, screenshots, code of debugging sessions or code that reproduces the issue if possible.
The best reproductions are in plain Zope installations without addons or at least with minimal needed addons installed.

-->

### What I did:

Create a zope instance:
```
mkwsgiinstance -d username_log_repro  -u  admin:admin
runwsgi  ./username_log_repro/etc/zope.ini
# add a `standard_error_message` at root ( this is necessary for error requests to be logged at all in access log - this looks like another independent issue )
curl -d id=standard_error_message 'http://admin:admin@127.0.0.1:8080/manage_addProduct/OFSP/addDTMLMethod'
```

Make a successful HTTP request and see in the log that username (`admin`) appears
```console
$ curl --silent -o /dev/null  http://admin:admin@127.0.0.1:8080 ; tail -n 1 username_log_repro/var/log/Z4.log
127.0.0.1 - admin [15/Sep/2023:16:13:03 +0200] "GET / HTTP/1.1" 200 2 "-" "curl/7.87.0"
```

Make an error HTTP request, the username field is empty:

```console
$ curl --silent -o /dev/null  http://admin:admin@127.0.0.1:8080/error ; tail -n 1 username_log_repro/var/log/Z4.log
127.0.0.1 - - [15/Sep/2023:16:14:30 +0200] "GET /error HTTP/1.1" 404 229 "-" "curl/7.87.0"
```


<!-- Enter a reproducible description, including preconditions. -->

### What I expect to happen:

The username field should be present even for error requests.  

### What actually happened:

The username field is empty, for error requests. This is not only for "404 not found" requests, but also for server side errors.

### What version of Python and Zope/Addons I am using:

This is on current master

<!-- Enter Operating system, Python and Zope versions you are using -->

---

I investigated and found that username is set in `environ` by https://github.com/zopefoundation/Zope/blob/59f68703c249a0a0f5b3b092395709820f221108/src/ZPublisher/WSGIPublisher.py#L388-L395 

but this code is not executed if `_publish` gets an exception. I'm making a pull request.
src/ZPublisher/tests/test_WSGIPublisher.py::TestPublishModule::test_set_REMOTE_USER_environ_error
src/ZPublisher/tests/test_WSGIPublisher.py::WSGIResponseTests::test___str___raises src/ZPublisher/tests/test_WSGIPublisher.py::WSGIResponseTests::test_debugError src/ZPublisher/tests/test_WSGIPublisher.py::WSGIResponseTests::test_exception_calls_unauthorized src/ZPublisher/tests/test_WSGIPublisher.py::WSGIResponseTests::test_finalize_sets_204_on_empty_not_streaming src/ZPublisher/tests/test_WSGIPublisher.py::WSGIResponseTests::test_finalize_sets_204_on_empty_not_streaming_ignores_non_200 src/ZPublisher/tests/test_WSGIPublisher.py::WSGIResponseTests::test_finalize_sets_content_length_if_missing src/ZPublisher/tests/test_WSGIPublisher.py::WSGIResponseTests::test_finalize_skips_content_length_if_missing_w_streaming src/ZPublisher/tests/test_WSGIPublisher.py::WSGIResponseTests::test_listHeaders_includes_Date_header src/ZPublisher/tests/test_WSGIPublisher.py::WSGIResponseTests::test_listHeaders_includes_Server_header_w_server_version_set src/ZPublisher/tests/test_WSGIPublisher.py::WSGIResponseTests::test_listHeaders_skips_Server_header_wo_server_version_set src/ZPublisher/tests/test_WSGIPublisher.py::WSGIResponseTests::test_setBody_IStreamIterator src/ZPublisher/tests/test_WSGIPublisher.py::WSGIResponseTests::test_setBody_IUnboundStreamIterator src/ZPublisher/tests/test_WSGIPublisher.py::WSGIResponseTests::test_setBody_w_locking src/ZPublisher/tests/test_WSGIPublisher.py::TestPublish::test_w_REMOTE_USER src/ZPublisher/tests/test_WSGIPublisher.py::TestPublish::test_wo_REMOTE_USER src/ZPublisher/tests/test_WSGIPublisher.py::TestPublishModule::testCustomExceptionViewBadRequest src/ZPublisher/tests/test_WSGIPublisher.py::TestPublishModule::testCustomExceptionViewConflictErrorHandling src/ZPublisher/tests/test_WSGIPublisher.py::TestPublishModule::testCustomExceptionViewForbidden src/ZPublisher/tests/test_WSGIPublisher.py::TestPublishModule::testCustomExceptionViewInternalError src/ZPublisher/tests/test_WSGIPublisher.py::TestPublishModule::testCustomExceptionViewNotFound src/ZPublisher/tests/test_WSGIPublisher.py::TestPublishModule::testCustomExceptionViewUnauthorized src/ZPublisher/tests/test_WSGIPublisher.py::TestPublishModule::testCustomExceptionViewZTKNotFound src/ZPublisher/tests/test_WSGIPublisher.py::TestPublishModule::testDebugExceptionsBypassesExceptionResponse src/ZPublisher/tests/test_WSGIPublisher.py::TestPublishModule::testHandleErrorsFalseBypassesExceptionResponse src/ZPublisher/tests/test_WSGIPublisher.py::TestPublishModule::testRedirectExceptionView src/ZPublisher/tests/test_WSGIPublisher.py::TestPublishModule::test_calls_setDefaultSkin src/ZPublisher/tests/test_WSGIPublisher.py::TestPublishModule::test_handle_ConflictError src/ZPublisher/tests/test_WSGIPublisher.py::TestPublishModule::test_publish_can_return_new_response src/ZPublisher/tests/test_WSGIPublisher.py::TestPublishModule::test_publish_returns_data_witten_to_response_before_body src/ZPublisher/tests/test_WSGIPublisher.py::TestPublishModule::test_raises_redirect src/ZPublisher/tests/test_WSGIPublisher.py::TestPublishModule::test_raises_unauthorized src/ZPublisher/tests/test_WSGIPublisher.py::TestPublishModule::test_request_closed src/ZPublisher/tests/test_WSGIPublisher.py::TestPublishModule::test_response_body_is_file src/ZPublisher/tests/test_WSGIPublisher.py::TestPublishModule::test_response_is_stream src/ZPublisher/tests/test_WSGIPublisher.py::TestPublishModule::test_response_is_unboundstream src/ZPublisher/tests/test_WSGIPublisher.py::TestPublishModule::test_set_REMOTE_USER_environ src/ZPublisher/tests/test_WSGIPublisher.py::TestPublishModule::test_stream_file_wrapper src/ZPublisher/tests/test_WSGIPublisher.py::TestPublishModule::test_stream_file_wrapper_without_read src/ZPublisher/tests/test_WSGIPublisher.py::TestPublishModule::test_unboundstream_file_wrapper src/ZPublisher/tests/test_WSGIPublisher.py::TestPublishModule::test_upgrades_ztk_not_found src/ZPublisher/tests/test_WSGIPublisher.py::TestPublishModule::test_webdav_source_port src/ZPublisher/tests/test_WSGIPublisher.py::ExcViewCreatedTests::testNoStandardErrorMessage src/ZPublisher/tests/test_WSGIPublisher.py::ExcViewCreatedTests::testWithEmptyErrorMessage src/ZPublisher/tests/test_WSGIPublisher.py::ExcViewCreatedTests::testWithStandardErrorMessage src/ZPublisher/tests/test_WSGIPublisher.py::WSGIPublisherTests::test_can_handle_non_ascii_URLs src/ZPublisher/tests/test_WSGIPublisher.py::TestLoadApp::test_no_second_transaction_is_created_if_closed src/ZPublisher/tests/test_WSGIPublisher.py::TestLoadApp::test_open_transaction_is_aborted