*** a/src/backend/commands/variable.c
--- b/src/backend/commands/variable.c
***************
*** 613,625 **** check_XactIsoLevel(char **newval, void **extra, GucSource source)
  			GUC_check_errmsg("SET TRANSACTION ISOLATION LEVEL must not be called in a subtransaction");
  			return false;
  		}
! 		/* Can't go to serializable mode while recovery is still active */
! 		if (newXactIsoLevel == XACT_SERIALIZABLE && RecoveryInProgress())
! 		{
! 			GUC_check_errmsg("cannot use serializable mode in a hot standby");
! 			GUC_check_errhint("You can use REPEATABLE READ instead.");
! 			return false;
! 		}
  	}
  
  	*extra = malloc(sizeof(int));
--- 613,624 ----
  			GUC_check_errmsg("SET TRANSACTION ISOLATION LEVEL must not be called in a subtransaction");
  			return false;
  		}
! 		/*
! 		 * NOTE: We cannot check for an attempt to set SERIALIZABLE
! 		 * transactions on a hot standby here, because when that is set as the
! 		 * default, this would get called before shared memory is even set up.
! 		 * Instead, this is checked when a serializable snapshot is requested.
! 		 */
  	}
  
  	*extra = malloc(sizeof(int));
*** a/src/backend/storage/lmgr/predicate.c
--- b/src/backend/storage/lmgr/predicate.c
***************
*** 1572,1577 **** GetSerializableTransactionSnapshot(Snapshot snapshot)
--- 1572,1596 ----
  	Assert(IsolationIsSerializable());
  
  	/*
+ 	 * Can't use serializable mode while recovery is still active, as it is,
+ 	 * for example, on a hot standby.
+ 	 */
+ 	if (RecoveryInProgress())
+ 	{
+ 		if (DefaultXactIsoLevel == XACT_SERIALIZABLE)
+ 			ereport(ERROR,
+ 					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ 					 errmsg("cannot use SERIALIZABLE mode in a hot standby"),
+ 					 errdetail("\"default_transaction_isolation\" is set to \"serializable\"."),
+ 					 errhint("You can use \"SET default_transaction_isolation = 'repeatable read'\" to change the default.")));
+ 		else
+ 			ereport(ERROR,
+ 					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ 					 errmsg("cannot use SERIALIZABLE mode in a hot standby"),
+ 					 errhint("You can use REPEATABLE READ instead.")));
+ 	}
+ 
+ 	/*
  	 * A special optimization is available for SERIALIZABLE READ ONLY
  	 * DEFERRABLE transactions -- we can wait for a suitable snapshot and
  	 * thereby avoid all SSI overhead once it's running.
*** a/src/backend/utils/init/postinit.c
--- b/src/backend/utils/init/postinit.c
***************
*** 584,589 **** InitPostgres(const char *in_dbname, Oid dboid, const char *username,
--- 584,597 ----
  		/* statement_timestamp must be set for timeouts to work correctly */
  		SetCurrentStatementStartTimestamp();
  		StartTransactionCommand();
+ 
+ 		/*
+ 		 * transaction_isolation will have been set to the default by the
+ 		 * above.  Connection to a hot standby will have a problem here if we
+ 		 * are in 'serializable' mode, so force isolation to something safe.
+ 		 */
+ 		SetConfigOption("transaction_isolation", "read committed",
+ 						PGC_SUSET, PGC_S_OVERRIDE);
  		(void) GetTransactionSnapshot();
  	}
  
