diff --git a/changes/bug29040 b/changes/bug29040
new file mode 100644
index 0000000000000000000000000000000000000000..0662aaa8a52334f76bb4ffedbaa79aeaaedd62e1
--- /dev/null
+++ b/changes/bug29040
@@ -0,0 +1,4 @@
+  o Minor bugfixes (onion services):
+    - Avoid crashing if ClientOnionAuthDir (incorrectly) contains
+      more than one private key for a hidden service. Fixes bug 29040;
+      bugfix on 0.3.5.1-alpha.
diff --git a/src/app/config/config.c b/src/app/config/config.c
index 952b9cd301166b43e4d08f95863595a65c4dea33..8e4794315f7dd66b345f77519b99314a01ef7742 100644
--- a/src/app/config/config.c
+++ b/src/app/config/config.c
@@ -1056,10 +1056,14 @@ config_free_all(void)
  * (We return "[scrubbed]" if SafeLogging is "1", and address otherwise.)
  */
 const char *
-safe_str_client(const char *address)
+safe_str_client_opts(const or_options_t *options, const char *address)
 {
   tor_assert(address);
-  if (get_options()->SafeLogging_ == SAFELOG_SCRUB_ALL)
+  if (!options) {
+    options = get_options();
+  }
+
+  if (options->SafeLogging_ == SAFELOG_SCRUB_ALL)
     return "[scrubbed]";
   else
     return address;
@@ -1073,10 +1077,14 @@ safe_str_client(const char *address)
  * otherwise.)
  */
 const char *
-safe_str(const char *address)
+safe_str_opts(const or_options_t *options, const char *address)
 {
   tor_assert(address);
-  if (get_options()->SafeLogging_ != SAFELOG_SCRUB_NONE)
+  if (!options) {
+    options = get_options();
+  }
+
+  if (options->SafeLogging_ != SAFELOG_SCRUB_NONE)
     return "[scrubbed]";
   else
     return address;
diff --git a/src/app/config/config.h b/src/app/config/config.h
index b3b31508254cf114dcc263236a6d83a7aeb31529..46db02f944a356a1834c8b0070e4bf5b5f3a56df 100644
--- a/src/app/config/config.h
+++ b/src/app/config/config.h
@@ -141,6 +141,16 @@ MOCK_DECL(char *,
 #define get_cachedir_fname_suffix(sub1, suffix) \
   options_get_cachedir_fname2_suffix(get_options(), (sub1), NULL, (suffix))
 
+#define safe_str_client(address) \
+  safe_str_client_opts(NULL, address)
+#define safe_str(address) \
+  safe_str_opts(NULL, address)
+
+const char * safe_str_client_opts(const or_options_t *options,
+                                  const char *address);
+const char * safe_str_opts(const or_options_t *options,
+                           const char *address);
+
 int using_default_dir_authorities(const or_options_t *options);
 
 int create_keys_directory(const or_options_t *options);
diff --git a/src/feature/hs/hs_client.c b/src/feature/hs/hs_client.c
index d4eee50bb7a0148c858fddac5d2cdbe07a6573bc..bd43ef6132cb130eb95ca024ea63af1144b5389f 100644
--- a/src/feature/hs/hs_client.c
+++ b/src/feature/hs/hs_client.c
@@ -1637,17 +1637,17 @@ hs_config_client_authorization(const or_options_t *options,
        * as a key of global map in the future. */
       if (hs_parse_address(auth->onion_address, &identity_pk,
                            NULL, NULL) < 0) {
-        client_service_authorization_free(auth);
         log_warn(LD_REND, "The onion address \"%s\" is invalid in "
                           "file %s", filename, auth->onion_address);
+        client_service_authorization_free(auth);
         continue;
       }
 
       if (digest256map_get(auths, identity_pk.pubkey)) {
-        client_service_authorization_free(auth);
         log_warn(LD_REND, "Duplicate authorization for the same hidden "
                           "service address %s.",
-                 safe_str_client(auth->onion_address));
+                 safe_str_client_opts(options, auth->onion_address));
+        client_service_authorization_free(auth);
         goto end;
       }