--- a/src/bin/pg_upgrade/check.c
+++ b/src/bin/pg_upgrade/check.c
@@ -33,6 +33,8 @@
 static void check_for_gist_inet_ops(ClusterInfo *cluster);
 static void check_for_nonstandard_string_settings(ClusterInfo *cluster);
 static void check_for_uuid_bytea_casts(ClusterInfo *cluster);
+static void collect_stored_setting_pairs(ClusterInfo *cluster);
+static void check_for_stored_setting_values(void);
 static void check_for_new_tablespace_dir(void);
 static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster);
 static void check_for_unicode_update(ClusterInfo *cluster);
@@ -708,6 +710,8 @@
 	if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1800)
 		check_for_uuid_bytea_casts(&old_cluster);
 
+	collect_stored_setting_pairs(&old_cluster);
+
 	/*
 	 * While not a check option, we do this now because this is the only time
 	 * the old server is running.
@@ -726,6 +730,7 @@
 	get_db_rel_and_slot_infos(&new_cluster);
 
 	check_new_cluster_is_empty();
+	check_for_stored_setting_values();
 
 	check_loadable_libraries();
 
@@ -2032,6 +2037,199 @@
 	}
 	else
 		check_ok();
+}
+
+typedef struct
+{
+	char	   *object;
+	char	   *name;
+	char	   *value;
+} StoredSettingPair;
+
+static StoredSettingPair *stored_setting_pairs = NULL;
+static int	n_stored_setting_pairs = 0;
+
+static void
+add_stored_setting_pair(const char *object, const char *setting)
+{
+	const char *eq = strchr(setting, '=');
+
+	if (eq == NULL)
+		return;
+
+	stored_setting_pairs = pg_realloc(stored_setting_pairs,
+									  (n_stored_setting_pairs + 1) * sizeof(StoredSettingPair));
+	stored_setting_pairs[n_stored_setting_pairs].object = pg_strdup(object);
+	stored_setting_pairs[n_stored_setting_pairs].name =
+		psprintf("%.*s", (int) (eq - setting), setting);
+	stored_setting_pairs[n_stored_setting_pairs].value = pg_strdup(eq + 1);
+	n_stored_setting_pairs++;
+}
+
+static void
+process_stored_setting_pairs(DbInfo *dbinfo, PGresult *res, void *arg)
+{
+	int			ntups = PQntuples(res);
+	int			i_proc = PQfnumber(res, "proc");
+	int			i_setting = PQfnumber(res, "setting");
+
+	for (int rowno = 0; rowno < ntups; rowno++)
+		add_stored_setting_pair(psprintf("function %s",
+										 PQgetvalue(res, rowno, i_proc)),
+								PQgetvalue(res, rowno, i_setting));
+}
+
+static void
+collect_stored_setting_pairs(ClusterInfo *cluster)
+{
+	UpgradeTask *task;
+	PGconn	   *conn;
+	PGresult   *res;
+
+	conn = connectToServer(cluster, "template1");
+	res = executeQueryOrDie(conn,
+							"SELECT d.datname, r.rolname, s.setting "
+							"FROM (SELECT setdatabase, setrole, "
+							"             pg_catalog.unnest(setconfig) AS setting "
+							"      FROM pg_catalog.pg_db_role_setting "
+							"      WHERE setdatabase <> 0 OR setrole <> 0) s "
+							"     LEFT JOIN pg_catalog.pg_database d "
+							"            ON d.oid = s.setdatabase "
+							"     LEFT JOIN pg_catalog.pg_roles r "
+							"            ON r.oid = s.setrole");
+
+	for (int rowno = 0; rowno < PQntuples(res); rowno++)
+	{
+		const char *datname = PQgetvalue(res, rowno, 0);
+		const char *rolname = PQgetvalue(res, rowno, 1);
+		char	   *object;
+
+		if (PQgetisnull(res, rowno, 1))
+			object = psprintf("database %s", datname);
+		else if (PQgetisnull(res, rowno, 0))
+			object = psprintf("role %s", rolname);
+		else
+			object = psprintf("role %s in database %s", rolname, datname);
+
+		add_stored_setting_pair(object, PQgetvalue(res, rowno, 2));
+	}
+
+	PQclear(res);
+	PQfinish(conn);
+
+	task = upgrade_task_create();
+	upgrade_task_add_step(task,
+						  "SELECT p.oid::pg_catalog.regprocedure AS proc, p.setting "
+						  "FROM (SELECT oid, pg_catalog.unnest(proconfig) AS setting "
+						  "      FROM pg_catalog.pg_proc "
+						  "      WHERE proconfig IS NOT NULL) p",
+						  process_stored_setting_pairs, true, NULL);
+	upgrade_task_run(task, cluster);
+	upgrade_task_free(task);
+}
+
+static void
+check_for_stored_setting_values(void)
+{
+	PGconn	   *conn;
+	PGresult   *res;
+	PQExpBufferData query;
+	FILE	   *script = NULL;
+	char		path[MAXPGPATH];
+	char	  **names = NULL;
+	int			n_names = 0;
+
+	if (n_stored_setting_pairs == 0)
+		return;
+
+	prep_status("Checking for stored settings the new cluster rejects");
+
+	snprintf(path, sizeof(path), "%s/%s",
+			 log_opts.basedir, "rejected_settings.txt");
+
+	conn = connectToServer(&new_cluster, "template1");
+
+	res = executeQueryOrDie(conn,
+							"SELECT name FROM pg_catalog.pg_settings "
+							"WHERE context IN ('user', 'superuser')");
+	names = pg_malloc(PQntuples(res) * sizeof(char *));
+	for (int rowno = 0; rowno < PQntuples(res); rowno++)
+		names[n_names++] = pg_strdup(PQgetvalue(res, rowno, 0));
+	PQclear(res);
+
+	initPQExpBuffer(&query);
+
+	for (int i = 0; i < n_stored_setting_pairs; i++)
+	{
+		bool		seen = false;
+		bool		known = false;
+
+		for (int j = 0; j < i && !seen; j++)
+			seen = (strcmp(stored_setting_pairs[j].name,
+						   stored_setting_pairs[i].name) == 0 &&
+					strcmp(stored_setting_pairs[j].value,
+						   stored_setting_pairs[i].value) == 0);
+		if (seen)
+			continue;
+
+		if (strcmp(stored_setting_pairs[i].name,
+				   "standard_conforming_strings") == 0)
+			continue;
+
+		for (int j = 0; j < n_names && !known; j++)
+			known = (strcmp(names[j], stored_setting_pairs[i].name) == 0);
+		if (!known)
+			continue;
+
+		resetPQExpBuffer(&query);
+		appendPQExpBufferStr(&query, "SELECT pg_catalog.set_config(");
+		appendStringLiteralConn(&query, stored_setting_pairs[i].name, conn);
+		appendPQExpBufferStr(&query, ", ");
+		appendStringLiteralConn(&query, stored_setting_pairs[i].value, conn);
+		appendPQExpBufferStr(&query, ", true)");
+		res = PQexec(conn, query.data);
+
+		if (PQresultStatus(res) != PGRES_TUPLES_OK)
+			for (int k = 0; k < n_stored_setting_pairs; k++)
+			{
+				if (strcmp(stored_setting_pairs[k].name,
+						   stored_setting_pairs[i].name) != 0 ||
+					strcmp(stored_setting_pairs[k].value,
+						   stored_setting_pairs[i].value) != 0)
+					continue;
+				if (script == NULL &&
+					(script = fopen_priv(path, "w")) == NULL)
+					pg_fatal("could not open file \"%s\": %m", path);
+				fprintf(script, "%s: %s = %s\n",
+						stored_setting_pairs[k].object,
+						stored_setting_pairs[i].name,
+						stored_setting_pairs[i].value);
+			}
+
+		PQclear(res);
+	}
+
+	termPQExpBuffer(&query);
+	PQfinish(conn);
+
+	for (int i = 0; i < n_names; i++)
+		pg_free(names[i]);
+	pg_free(names);
+
+	if (script)
+	{
+		fclose(script);
+		pg_log(PG_REPORT, "fatal");
+		pg_fatal("Your installation contains roles, databases, or functions that store\n"
+				 "a value the new cluster does not accept for a setting.\n"
+				 "The upgrade would fail restoring them.\n"
+				 "Change those settings to a value the new cluster accepts and restart\n"
+				 "the upgrade.\n"
+				 "A list of the settings is in the file:\n"
+				 "    %s", path);
+	}
+	else
+		check_ok();
 }
 
 /*
