diff --git a/installation/language/en-GB/en-GB.ini b/installation/language/en-GB/en-GB.ini
index 1ea6a65f2dc44..7ee5c8fa64af8 100644
--- a/installation/language/en-GB/en-GB.ini
+++ b/installation/language/en-GB/en-GB.ini
@@ -65,6 +65,7 @@ INSTL_DATABASE_NO_SCHEMA="No database schema exists for this database type."
INSTL_DATABASE_PASSWORD_DESC="Either a password you created or a password provided by your host."
INSTL_DATABASE_PREFIX_DESC="Enter a table prefix or use the randomly generated one."
INSTL_DATABASE_PREFIX_MSG="The table prefix must start with a letter, optionally be followed by alphanumeric characters and by an underscore"
+INSTL_DATABASE_RESPONSE_ERROR="The latest request returned an invalid response:"
INSTL_DATABASE_TYPE_DESC="Select the database type."
INSTL_DATABASE_USER_DESC="Either a username you created or a username provided by your host."
INSTL_DATABASE_VALIDATION_ERROR="Check your database credentials, database type, database name or hostname. If you have MySQL 8 installed then please read this wiki for more information."
diff --git a/installation/language/en-US/en-US.ini b/installation/language/en-US/en-US.ini
index 8c311fbf5f7e4..5ca026f9fb208 100644
--- a/installation/language/en-US/en-US.ini
+++ b/installation/language/en-US/en-US.ini
@@ -65,6 +65,7 @@ INSTL_DATABASE_NO_SCHEMA="No database schema exists for this database type."
INSTL_DATABASE_PASSWORD_DESC="Either a password you created or a password provided by your host."
INSTL_DATABASE_PREFIX_DESC="Enter a table prefix or use the randomly generated one."
INSTL_DATABASE_PREFIX_MSG="The table prefix must start with a letter, optionally be followed by alphanumeric characters and by an underscore"
+INSTL_DATABASE_RESPONSE_ERROR="The latest request returned an invalid response:"
INSTL_DATABASE_TYPE_DESC="Select the database type."
INSTL_DATABASE_USER_DESC="Either a username you created or a username provided by your host."
INSTL_DATABASE_VALIDATION_ERROR="Check your database credentials, database type, database name or hostname. If you have MySQL 8 installed then please read this wiki for more information."
diff --git a/installation/template/index.php b/installation/template/index.php
index 5e3de0e4a2ca1..07988f5e38090 100644
--- a/installation/template/index.php
+++ b/installation/template/index.php
@@ -49,6 +49,8 @@
Text::script('INSTL_PROCESS_BUSY');
Text::script('INSTL_FTP_SETTINGS_CORRECT');
+Text::script('INSTL_DATABASE_RESPONSE_ERROR');
+
// Load strings for translated messages (directory removal)
Text::script('INSTL_REMOVE_INST_FOLDER');
Text::script('INSTL_COMPLETE_REMOVE_FOLDER');
diff --git a/installation/template/js/setup.js b/installation/template/js/setup.js
index 7e02da13b509d..7e78b2772d770 100644
--- a/installation/template/js/setup.js
+++ b/installation/template/js/setup.js
@@ -83,8 +83,15 @@ Joomla.checkDbCredentials = function() {
perform: true,
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
onSuccess: function(response, xhr){
- response = JSON.parse(response);
var loaderElement = document.querySelector('joomla-core-loader');
+ try {
+ response = JSON.parse(response);
+ } catch (e) {
+ loaderElement.parentNode.removeChild(loaderElement);
+ Joomla.renderMessages({'error': [Joomla.JText._('INSTL_DATABASE_RESPONSE_ERROR'), response]});
+
+ return false;
+ }
if (response.messages) {
Joomla.renderMessages(response.messages);
diff --git a/installation/template/js/template.js b/installation/template/js/template.js
index 32fbf67f52343..65c37b4a857df 100644
--- a/installation/template/js/template.js
+++ b/installation/template/js/template.js
@@ -185,10 +185,19 @@
data: data,
perform: true,
onSuccess: function(response, xhr){
- response = JSON.parse(response);
- Joomla.replaceTokens(response.token);
var spinnerElement = document.querySelector('joomla-core-loader');
+ try {
+ response = JSON.parse(response);
+ } catch (e) {
+ spinnerElement.parentNode.removeChild(spinnerElement);
+ Joomla.renderMessages({'error': [Joomla.JText._('INSTL_DATABASE_RESPONSE_ERROR'), response]});
+
+ return false;
+ }
+
+ Joomla.replaceTokens(response.token);
+
if (response.error === true)
{
spinnerElement.parentNode.removeChild(spinnerElement);