diff --git a/CRM/Core/Payment/Stripe.php b/CRM/Core/Payment/Stripe.php
index 16855b72d9dadfade7ae43c4f58d91262fd86c1f..bc29ad03b79bdd13f7b44beec44a11f21e6aeb70 100644
--- a/CRM/Core/Payment/Stripe.php
+++ b/CRM/Core/Payment/Stripe.php
@@ -363,6 +363,15 @@ class CRM_Core_Payment_Stripe extends CRM_Core_Payment {
         \Civi::log('stripe')->error($this->getLogPrefix() . $op . ': ' . get_class($e) . ': ' . $e->getMessage() . print_r($e->getJsonBody(),TRUE));
         return $e->getJsonBody()['error'] ?? $genericError;
 
+      case 'Stripe\Exception\PermissionException':
+        // The client is probably setup with a restricted API key and does not have permission to do the requested action.
+        // We should not display the specific error to the end customer but we *do* want the details in the log.
+        // For example, if we have a readonly API key we won't be able to update Stripe customer metadata, but we may choose to continue!
+        \Civi::log('stripe')->warning($this->getLogPrefix() . $op . ': ' . get_class($e) . ': ' . $e->getMessage());
+        $genericError['code'] = $e->getStripeCode();
+        $genericError['message'] = $e->getMessage();
+        return $genericError;
+
       default:
         // Something else happened, completely unrelated to Stripe
         \Civi::log('stripe')->error($this->getLogPrefix() . $op . ' (unknown error): ' . get_class($e) . ': ' . $e->getMessage());
diff --git a/CRM/Stripe/BAO/StripeCustomer.php b/CRM/Stripe/BAO/StripeCustomer.php
index 9f3d57fb64fdda671a0ab40dc08c7cf0dd7fbe89..24346d06f89e2581025b41f5ee9741b7551ca4cf 100644
--- a/CRM/Stripe/BAO/StripeCustomer.php
+++ b/CRM/Stripe/BAO/StripeCustomer.php
@@ -4,6 +4,7 @@ use Civi\Api4\Contact;
 use Civi\Api4\Email;
 use Civi\Api4\Extension;
 use Civi\Api4\StripeCustomer;
+use Civi\Payment\Exception\PaymentProcessorException;
 use CRM_Stripe_ExtensionUtil as E;
 
 class CRM_Stripe_BAO_StripeCustomer extends CRM_Stripe_DAO_StripeCustomer {
@@ -72,15 +73,15 @@ class CRM_Stripe_BAO_StripeCustomer extends CRM_Stripe_DAO_StripeCustomer {
    * @param \CRM_Core_Payment_Stripe $stripe
    * @param string $stripeCustomerID
    *
-   * @return \Stripe\Customer
+   * @return string
    * @throws \CRM_Core_Exception
    * @throws \Civi\Payment\Exception\PaymentProcessorException
    */
-  public static function updateMetadata(array $params, \CRM_Core_Payment_Stripe $stripe, string $stripeCustomerID) {
+  public static function updateMetadata(array $params, \CRM_Core_Payment_Stripe $stripe, string $stripeCustomerID): string {
     $requiredParams = ['contact_id'];
     foreach ($requiredParams as $required) {
       if (empty($params[$required])) {
-        throw new \Civi\Payment\Exception\PaymentProcessorException('Stripe Customer (updateMetadata): Missing required parameter: ' . $required);
+        throw new PaymentProcessorException('Stripe Customer (updateMetadata): Missing required parameter: ' . $required);
       }
     }
 
@@ -91,10 +92,15 @@ class CRM_Stripe_BAO_StripeCustomer extends CRM_Stripe_DAO_StripeCustomer {
     }
     catch (Exception $e) {
       $err = $stripe->parseStripeException('create_customer', $e);
-      \Civi::log('stripe')->error('Failed to create Stripe Customer: ' . $err['message'] . '; ' . print_r($err, TRUE));
-      throw new \Civi\Payment\Exception\PaymentProcessorException('Failed to update Stripe Customer: ' . $err['code']);
+      if ($e instanceof \Stripe\Exception\PermissionException) {
+        \Civi::log('stripe')->warning('Could not update Stripe Customer metadata for StripeCustomerID: ' . $stripeCustomerID . '; contactID: ' . $params['contact_id']);
+      }
+      else {
+        \Civi::log('stripe')->error('Failed to create Stripe Customer: ' . $err['message'] . '; ' . print_r($err, TRUE));
+        throw new PaymentProcessorException('Failed to update Stripe Customer: ' . $err['code']);
+      }
     }
-    return $stripeCustomer;
+    return $stripeCustomer ?? '';
   }
 
   /**
diff --git a/Civi/Api4/Action/StripeCustomer/UpdateStripe.php b/Civi/Api4/Action/StripeCustomer/UpdateStripe.php
index 975122e2c275def3f0ab4e07aff4fde5521bbd11..6fdab2bfc3bbec3bafdeab5e941b6fa713dba6fd 100644
--- a/Civi/Api4/Action/StripeCustomer/UpdateStripe.php
+++ b/Civi/Api4/Action/StripeCustomer/UpdateStripe.php
@@ -94,9 +94,10 @@ class UpdateStripe extends \Civi\Api4\Generic\AbstractAction {
 
     /** @var \CRM_Core_Payment_Stripe $paymentProcessor */
     $paymentProcessor = \Civi\Payment\System::singleton()->getById($this->paymentProcessorID);
-    $stripeCustomer = \CRM_Stripe_BAO_StripeCustomer::updateMetadata(['contact_id' => $this->contactID, 'description' => $this->description], $paymentProcessor, $this->customerID);
+    $stripeCustomerID = \CRM_Stripe_BAO_StripeCustomer::updateMetadata(['contact_id' => $this->contactID, 'description' => $this->description], $paymentProcessor, $this->customerID);
 
-    $result->exchangeArray($stripeCustomer->toArray());
+    // Return values may change!
+    $result->exchangeArray(['stripeCustomerID' => $stripeCustomerID]);
   }
 
 }