diff --git a/src/components/structures/auth/ForgotPassword.js b/src/components/structures/auth/ForgotPassword.js
index 2ea39ad657..e235446b16 100644
--- a/src/components/structures/auth/ForgotPassword.js
+++ b/src/components/structures/auth/ForgotPassword.js
@@ -22,7 +22,7 @@ import sdk from '../../../index';
 import Modal from "../../../Modal";
 import SdkConfig from "../../../SdkConfig";
 import PasswordReset from "../../../PasswordReset";
-import {ValidatedServerConfig} from "../../../utils/AutoDiscoveryUtils";
+import AutoDiscoveryUtils, {ValidatedServerConfig} from "../../../utils/AutoDiscoveryUtils";
 
 // Phases
 // Show controls to configure server details
@@ -53,9 +53,40 @@ module.exports = React.createClass({
             password: "",
             password2: "",
             errorText: null,
+
+            // We perform liveliness checks later, but for now suppress the errors.
+            // We also track the server dead errors independently of the regular errors so
+            // that we can render it differently, and override any other error the user may
+            // be seeing.
+            serverIsAlive: true,
+            serverDeadError: "",
         };
     },
 
+    componentWillMount: function() {
+        this._checkServerLiveliness(this.props.serverConfig);
+    },
+
+    componentWillReceiveProps: async function(newProps) {
+        if (newProps.serverConfig.hsUrl === this.props.serverConfig.hsUrl &&
+            newProps.serverConfig.isUrl === this.props.serverConfig.isUrl) return;
+
+        // Do a liveliness check on the new URLs
+        this._checkServerLiveliness(newProps.serverConfig);
+    },
+
+    _checkServerLiveliness: async function(serverConfig) {
+        try {
+            await AutoDiscoveryUtils.validateServerConfigWithStaticUrls(
+                serverConfig.hsUrl,
+                serverConfig.isUrl,
+            );
+            this.setState({serverIsAlive: true});
+        } catch (e) {
+            this.setState(AutoDiscoveryUtils.authComponentStateForError(e));
+        }
+    },
+
     submitPasswordReset: function(email, password) {
         this.setState({
             phase: PHASE_SENDING_EMAIL,
@@ -89,6 +120,8 @@ module.exports = React.createClass({
     onSubmitForm: function(ev) {
         ev.preventDefault();
 
+        if (!this.state.serverIsAlive) return;
+
         if (!this.state.email) {
             this.showErrorDialog(_t('The email address linked to your account must be entered.'));
         } else if (!this.state.password || !this.state.password2) {
@@ -173,11 +206,21 @@ module.exports = React.createClass({
         const Field = sdk.getComponent('elements.Field');
 
         let errorText = null;
-        const err = this.state.errorText || this.props.defaultServerDiscoveryError;
+        const err = this.state.errorText;
         if (err) {
             errorText = <div className="mx_Login_error">{ err }</div>;
         }
 
+        let serverDeadSection;
+        if (!this.state.serverIsAlive) {
+            // TODO: TravisR - Design from Nad
+            serverDeadSection = (
+                <div className="mx_Login_error">
+                    {this.state.serverDeadError}
+                </div>
+            );
+        }
+
         let yourMatrixAccountText = _t('Your Matrix account on %(serverName)s', {
             serverName: this.props.serverConfig.hsName,
         });
@@ -207,11 +250,12 @@ module.exports = React.createClass({
         }
 
         return <div>
+            {errorText}
+            {serverDeadSection}
             <h3>
                 {yourMatrixAccountText}
                 {editLink}
             </h3>
-            {errorText}
             <form onSubmit={this.onSubmitForm}>
                 <div className="mx_AuthBody_fieldRow">
                     <Field
@@ -246,7 +290,12 @@ module.exports = React.createClass({
                     'A verification email will be sent to your inbox to confirm ' +
                     'setting your new password.',
                 )}</span>
-                <input className="mx_Login_submit" type="submit" value={_t('Send Reset Email')} />
+                <input
+                    className="mx_Login_submit"
+                    type="submit"
+                    value={_t('Send Reset Email')}
+                    disabled={!this.state.serverIsAlive}
+                />
             </form>
             <a className="mx_AuthBody_changeFlow" onClick={this.onLoginClick} href="#">
                 {_t('Sign in instead')}
diff --git a/src/components/structures/auth/Login.js b/src/components/structures/auth/Login.js
index b556057cdb..c38d59caeb 100644
--- a/src/components/structures/auth/Login.js
+++ b/src/components/structures/auth/Login.js
@@ -94,6 +94,13 @@ module.exports = React.createClass({
             phase: PHASE_LOGIN,
             // The current login flow, such as password, SSO, etc.
             currentFlow: "m.login.password",
+
+            // We perform liveliness checks later, but for now suppress the errors.
+            // We also track the server dead errors independently of the regular errors so
+            // that we can render it differently, and override any other error the user may
+            // be seeing.
+            serverIsAlive: true,
+            serverDeadError: "",
         };
     },
 
@@ -233,7 +240,7 @@ module.exports = React.createClass({
             username: username,
             busy: doWellknownLookup, // unset later by the result of onServerConfigChange
             errorText: null,
-            canTryLogin: true,
+            canTryLogin: this.state.serverIsAlive,
         });
         if (doWellknownLookup) {
             const serverName = username.split(':').slice(1).join(':');
@@ -247,7 +254,19 @@ module.exports = React.createClass({
                 if (e.translatedMessage) {
                     message = e.translatedMessage;
                 }
-                this.setState({errorText: message, busy: false, canTryLogin: false});
+
+                let errorText = message;
+                let discoveryState = {};
+                if (AutoDiscoveryUtils.isLivelinessError(e)) {
+                    errorText = this.state.errorText;
+                    discoveryState = this._stateForDiscoveryError(e);
+                }
+
+                this.setState({
+                    busy: false,
+                    errorText,
+                    ...discoveryState,
+                });
             }
         }
     },
@@ -272,7 +291,7 @@ module.exports = React.createClass({
         } else {
             this.setState({
                 errorText: null,
-                canTryLogin: true,
+                canTryLogin: this.state.serverIsAlive,
             });
         }
     },
@@ -297,13 +316,25 @@ module.exports = React.createClass({
         });
     },
 
-    _initLoginLogic: function(hsUrl, isUrl) {
-        const self = this;
+    _stateForDiscoveryError: function(err) {
+        return {
+            canTryLogin: false,
+            ...AutoDiscoveryUtils.authComponentStateForError(err),
+        };
+    },
+
+    _initLoginLogic: async function(hsUrl, isUrl) {
         hsUrl = hsUrl || this.props.serverConfig.hsUrl;
         isUrl = isUrl || this.props.serverConfig.isUrl;
 
-        // TODO: TravisR - Only use this if the homeserver is the default homeserver
-        const fallbackHsUrl = this.props.fallbackHsUrl;
+        let isDefaultServer = false;
+        if (this.props.serverConfig.isDefault
+            && hsUrl === this.props.serverConfig.hsUrl
+            && isUrl === this.props.serverConfig.isUrl) {
+            isDefaultServer = true;
+        }
+
+        const fallbackHsUrl = isDefaultServer ? this.props.fallbackHsUrl : null;
 
         const loginLogic = new Login(hsUrl, isUrl, fallbackHsUrl, {
             defaultDeviceDisplayName: this.props.defaultDeviceDisplayName,
@@ -315,6 +346,19 @@ module.exports = React.createClass({
             loginIncorrect: false,
         });
 
+        // Do a quick liveliness check on the URLs
+        try {
+            await AutoDiscoveryUtils.validateServerConfigWithStaticUrls(hsUrl, isUrl);
+            this.setState({serverIsAlive: true, errorText: "", canTryLogin: true});
+        } catch (e) {
+            const discoveryState = this._stateForDiscoveryError(e);
+            this.setState({
+                busy: false,
+                ...discoveryState,
+            });
+            return; // Server is dead - do not continue.
+        }
+
         loginLogic.getFlows().then((flows) => {
             // look for a flow where we understand all of the steps.
             for (let i = 0; i < flows.length; i++ ) {
@@ -339,14 +383,14 @@ module.exports = React.createClass({
                         "supported by this client.",
                 ),
             });
-        }, function(err) {
-            self.setState({
-                errorText: self._errorTextFromError(err),
+        }, (err) => {
+            this.setState({
+                errorText: this._errorTextFromError(err),
                 loginIncorrect: false,
                 canTryLogin: false,
             });
-        }).finally(function() {
-            self.setState({
+        }).finally(() => {
+            this.setState({
                 busy: false,
             });
         }).done();
@@ -485,7 +529,7 @@ module.exports = React.createClass({
                onForgotPasswordClick={this.props.onForgotPasswordClick}
                loginIncorrect={this.state.loginIncorrect}
                serverConfig={this.props.serverConfig}
-               disableSubmit={this.isBusy()}
+               disableSubmit={this.isBusy() || !this.state.serverIsAlive}
             />
         );
     },
@@ -522,6 +566,16 @@ module.exports = React.createClass({
             );
         }
 
+        let serverDeadSection;
+        if (!this.state.serverIsAlive) {
+            // TODO: TravisR - Design from Nad
+            serverDeadSection = (
+                <div className="mx_Login_error">
+                    {this.state.serverDeadError}
+                </div>
+            );
+        }
+
         return (
             <AuthPage>
                 <AuthHeader />
@@ -531,6 +585,7 @@ module.exports = React.createClass({
                         {loader}
                     </h2>
                     { errorTextSection }
+                    { serverDeadSection }
                     { this.renderServerComponent() }
                     { this.renderLoginComponentForStep() }
                     <a className="mx_AuthBody_changeFlow" onClick={this.onRegisterClick} href="#">
diff --git a/src/components/structures/auth/Registration.js b/src/components/structures/auth/Registration.js
index 6e4f076091..bf46c7520d 100644
--- a/src/components/structures/auth/Registration.js
+++ b/src/components/structures/auth/Registration.js
@@ -26,7 +26,7 @@ import { _t, _td } from '../../../languageHandler';
 import SdkConfig from '../../../SdkConfig';
 import { messageForResourceLimitError } from '../../../utils/ErrorUtils';
 import * as ServerType from '../../views/auth/ServerTypeSelector';
-import {ValidatedServerConfig} from "../../../utils/AutoDiscoveryUtils";
+import AutoDiscoveryUtils, {ValidatedServerConfig} from "../../../utils/AutoDiscoveryUtils";
 
 // Phases
 // Show controls to configure server details
@@ -79,6 +79,13 @@ module.exports = React.createClass({
             // Phase of the overall registration dialog.
             phase: PHASE_REGISTRATION,
             flows: null,
+
+            // We perform liveliness checks later, but for now suppress the errors.
+            // We also track the server dead errors independently of the regular errors so
+            // that we can render it differently, and override any other error the user may
+            // be seeing.
+            serverIsAlive: true,
+            serverDeadError: "",
         };
     },
 
@@ -152,6 +159,19 @@ module.exports = React.createClass({
             errorText: null,
         });
         if (!serverConfig) serverConfig = this.props.serverConfig;
+
+        // Do a liveliness check on the URLs
+        try {
+            await AutoDiscoveryUtils.validateServerConfigWithStaticUrls(
+                serverConfig.hsUrl,
+                serverConfig.isUrl,
+            );
+            this.setState({serverIsAlive: true});
+        } catch (e) {
+            this.setState(AutoDiscoveryUtils.authComponentStateForError(e));
+            return; // Server is dead - do not continue.
+        }
+
         const {hsUrl, isUrl} = serverConfig;
         this._matrixClient = Matrix.createClient({
             baseUrl: hsUrl,
@@ -447,6 +467,7 @@ module.exports = React.createClass({
                 onEditServerDetailsClick={onEditServerDetailsClick}
                 flows={this.state.flows}
                 serverConfig={this.props.serverConfig}
+                canSubmit={this.state.serverIsAlive}
             />;
         }
     },
@@ -462,6 +483,16 @@ module.exports = React.createClass({
             errorText = <div className="mx_Login_error">{ err }</div>;
         }
 
+        let serverDeadSection;
+        if (!this.state.serverIsAlive) {
+            // TODO: TravisR - Design from Nad
+            serverDeadSection = (
+                <div className="mx_Login_error">
+                    {this.state.serverDeadError}
+                </div>
+            );
+        }
+
         const signIn = <a className="mx_AuthBody_changeFlow" onClick={this.onLoginClick} href="#">
             { _t('Sign in instead') }
         </a>;
@@ -480,6 +511,7 @@ module.exports = React.createClass({
                 <AuthBody>
                     <h2>{ _t('Create your account') }</h2>
                     { errorText }
+                    { serverDeadSection }
                     { this.renderServerComponent() }
                     { this.renderRegisterComponent() }
                     { goBack }
diff --git a/src/components/views/auth/ModularServerConfig.js b/src/components/views/auth/ModularServerConfig.js
index 5a3bc23596..b5af58adf1 100644
--- a/src/components/views/auth/ModularServerConfig.js
+++ b/src/components/views/auth/ModularServerConfig.js
@@ -108,6 +108,8 @@ export default class ModularServerConfig extends React.PureComponent {
                 busy: false,
                 errorText: message,
             });
+
+            return null;
         }
     }
 
@@ -132,7 +134,8 @@ export default class ModularServerConfig extends React.PureComponent {
     onSubmit = async (ev) => {
         ev.preventDefault();
         ev.stopPropagation();
-        await this.validateServer();
+        const result = await this.validateServer();
+        if (!result) return; // Do not continue.
 
         if (this.props.onAfterSubmit) {
             this.props.onAfterSubmit();
diff --git a/src/components/views/auth/RegistrationForm.js b/src/components/views/auth/RegistrationForm.js
index b1af6ea42c..ccbfc507c6 100644
--- a/src/components/views/auth/RegistrationForm.js
+++ b/src/components/views/auth/RegistrationForm.js
@@ -53,11 +53,13 @@ module.exports = React.createClass({
         onEditServerDetailsClick: PropTypes.func,
         flows: PropTypes.arrayOf(PropTypes.object).isRequired,
         serverConfig: PropTypes.instanceOf(ValidatedServerConfig).isRequired,
+        canSubmit: PropTypes.bool,
     },
 
     getDefaultProps: function() {
         return {
             onValidationChange: console.error,
+            canSubmit: true,
         };
     },
 
@@ -80,6 +82,8 @@ module.exports = React.createClass({
     onSubmit: async function(ev) {
         ev.preventDefault();
 
+        if (!this.props.canSubmit) return;
+
         const allFieldsValid = await this.verifyFieldsBeforeSubmit();
         if (!allFieldsValid) {
             return;
@@ -540,7 +544,7 @@ module.exports = React.createClass({
         }
 
         const registerButton = (
-            <input className="mx_Login_submit" type="submit" value={_t("Register")} />
+            <input className="mx_Login_submit" type="submit" value={_t("Register")} disabled={!this.props.canSubmit} />
         );
 
         return (
diff --git a/src/components/views/auth/ServerConfig.js b/src/components/views/auth/ServerConfig.js
index 3967f49f18..8d2e2e7bba 100644
--- a/src/components/views/auth/ServerConfig.js
+++ b/src/components/views/auth/ServerConfig.js
@@ -109,6 +109,8 @@ export default class ServerConfig extends React.PureComponent {
                 busy: false,
                 errorText: message,
             });
+
+            return null;
         }
     }
 
@@ -137,7 +139,8 @@ export default class ServerConfig extends React.PureComponent {
     onSubmit = async (ev) => {
         ev.preventDefault();
         ev.stopPropagation();
-        await this.validateServer();
+        const result = await this.validateServer();
+        if (!result) return; // Do not continue.
 
         if (this.props.onAfterSubmit) {
             this.props.onAfterSubmit();
diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json
index 7673b5f6ab..2b5efc38ee 100644
--- a/src/i18n/strings/en_EN.json
+++ b/src/i18n/strings/en_EN.json
@@ -249,8 +249,11 @@
     "%(names)s and %(count)s others are typing …|other": "%(names)s and %(count)s others are typing …",
     "%(names)s and %(count)s others are typing …|one": "%(names)s and one other is typing …",
     "%(names)s and %(lastPerson)s are typing …": "%(names)s and %(lastPerson)s are typing …",
+    "Server failed liveliness check": "Server failed liveliness check",
+    "Server failed syntax check": "Server failed syntax check",
     "No homeserver URL provided": "No homeserver URL provided",
     "Unexpected error resolving homeserver configuration": "Unexpected error resolving homeserver configuration",
+    "Unexpected error resolving identity server configuration": "Unexpected error resolving identity server configuration",
     "This homeserver has hit its Monthly Active User limit.": "This homeserver has hit its Monthly Active User limit.",
     "This homeserver has exceeded one of its resource limits.": "This homeserver has exceeded one of its resource limits.",
     "Please <a>contact your service administrator</a> to continue using the service.": "Please <a>contact your service administrator</a> to continue using the service.",
@@ -304,7 +307,6 @@
     "Custom user status messages": "Custom user status messages",
     "Group & filter rooms by custom tags (refresh to apply changes)": "Group & filter rooms by custom tags (refresh to apply changes)",
     "Render simple counters in room header": "Render simple counters in room header",
-    "Custom Notification Sounds": "Custom Notification Sounds",
     "Edit messages after they have been sent (refresh to apply changes)": "Edit messages after they have been sent (refresh to apply changes)",
     "React to messages with emoji (refresh to apply changes)": "React to messages with emoji (refresh to apply changes)",
     "Enable Emoji suggestions while typing": "Enable Emoji suggestions while typing",
diff --git a/src/utils/AutoDiscoveryUtils.js b/src/utils/AutoDiscoveryUtils.js
index 0850039344..405215c237 100644
--- a/src/utils/AutoDiscoveryUtils.js
+++ b/src/utils/AutoDiscoveryUtils.js
@@ -15,10 +15,15 @@ limitations under the License.
 */
 
 import {AutoDiscovery} from "matrix-js-sdk";
-import {_td, newTranslatableError} from "../languageHandler";
+import {_t, _td, newTranslatableError} from "../languageHandler";
 import {makeType} from "./TypeUtils";
 import SdkConfig from "../SdkConfig";
 
+const LIVLINESS_DISCOVERY_ERRORS = [
+    AutoDiscovery.ERROR_INVALID_HOMESERVER,
+    AutoDiscovery.ERROR_INVALID_IDENTITY_SERVER,
+];
+
 export class ValidatedServerConfig {
     hsUrl: string;
     hsName: string;
@@ -31,7 +36,52 @@ export class ValidatedServerConfig {
 }
 
 export default class AutoDiscoveryUtils {
-    static async validateServerConfigWithStaticUrls(homeserverUrl: string, identityUrl: string): ValidatedServerConfig {
+    /**
+     * Checks if a given error or error message is considered an error
+     * relating to the liveliness of the server. Must be an error returned
+     * from this AutoDiscoveryUtils class.
+     * @param {string|Error} error The error to check
+     * @returns {boolean} True if the error is a liveliness error.
+     */
+    static isLivelinessError(error: string|Error): boolean {
+        if (!error) return false;
+        return !!LIVLINESS_DISCOVERY_ERRORS.find(e => e === error || e === error.message);
+    }
+
+    /**
+     * Gets the common state for auth components (login, registration, forgot
+     * password) for a given validation error.
+     * @param {Error} err The error encountered.
+     * @returns {{serverDeadError: (string|*), serverIsAlive: boolean}} The state
+     * for the component, given the error.
+     */
+    static authComponentStateForError(err: Error): {serverIsAlive: boolean, serverDeadError: string} {
+        if (AutoDiscoveryUtils.isLivelinessError(err)) {
+            // TODO: TravisR - Copy from Nad
+            return {
+                serverIsAlive: false,
+                serverDeadError: _t("Server failed liveliness check"),
+            };
+        } else {
+            // TODO: TravisR - Copy from Nad
+            return {
+                serverIsAlive: false,
+                serverDeadError: _t("Server failed syntax check"),
+            };
+        }
+    }
+
+    /**
+     * Validates a server configuration, using a pair of URLs as input.
+     * @param {string} homeserverUrl The homeserver URL.
+     * @param {string} identityUrl The identity server URL.
+     * @param {boolean} syntaxOnly If true, errors relating to liveliness of the servers will
+     * not be raised.
+     * @returns {Promise<ValidatedServerConfig>} Resolves to the validated configuration.
+     */
+    static async validateServerConfigWithStaticUrls(
+        homeserverUrl: string, identityUrl: string, syntaxOnly = false): ValidatedServerConfig {
+
         if (!homeserverUrl) {
             throw newTranslatableError(_td("No homeserver URL provided"));
         }
@@ -50,15 +100,33 @@ export default class AutoDiscoveryUtils {
         const url = new URL(homeserverUrl);
         const serverName = url.hostname;
 
-        return AutoDiscoveryUtils.buildValidatedConfigFromDiscovery(serverName, result);
+        return AutoDiscoveryUtils.buildValidatedConfigFromDiscovery(serverName, result, syntaxOnly);
     }
 
-    static async validateServerName(serverName: string): ValidatedServerConfig {
+    /**
+     * Validates a server configuration, using a homeserver domain name as input.
+     * @param {string} serverName The homeserver domain name (eg: "matrix.org") to validate.
+     * @param {boolean} syntaxOnly If true, errors relating to liveliness of the servers will
+     * not be raised.
+     * @returns {Promise<ValidatedServerConfig>} Resolves to the validated configuration.
+     */
+    static async validateServerName(serverName: string, syntaxOnly=false): ValidatedServerConfig {
         const result = await AutoDiscovery.findClientConfig(serverName);
         return AutoDiscoveryUtils.buildValidatedConfigFromDiscovery(serverName, result);
     }
 
-    static buildValidatedConfigFromDiscovery(serverName: string, discoveryResult): ValidatedServerConfig {
+    /**
+     * Validates a server configuration, using a pre-calculated AutoDiscovery result as
+     * input.
+     * @param {string} serverName The domain name the AutoDiscovery result is for.
+     * @param {*} discoveryResult The AutoDiscovery result.
+     * @param {boolean} syntaxOnly If true, errors relating to liveliness of the servers will
+     * not be raised.
+     * @returns {Promise<ValidatedServerConfig>} Resolves to the validated configuration.
+     */
+    static buildValidatedConfigFromDiscovery(
+        serverName: string, discoveryResult, syntaxOnly=false): ValidatedServerConfig {
+
         if (!discoveryResult || !discoveryResult["m.homeserver"]) {
             // This shouldn't happen without major misconfiguration, so we'll log a bit of information
             // in the log so we can find this bit of codee but otherwise tell teh user "it broke".
@@ -68,19 +136,27 @@ export default class AutoDiscoveryUtils {
 
         const hsResult = discoveryResult['m.homeserver'];
         if (hsResult.state !== AutoDiscovery.SUCCESS) {
-            if (AutoDiscovery.ALL_ERRORS.indexOf(hsResult.error) !== -1) {
-                throw newTranslatableError(hsResult.error);
-            }
-            throw newTranslatableError(_td("Unexpected error resolving homeserver configuration"));
+            console.error("Error processing homeserver config:", hsResult);
+            if (!syntaxOnly || !AutoDiscoveryUtils.isLivelinessError(hsResult.error)) {
+                if (AutoDiscovery.ALL_ERRORS.indexOf(hsResult.error) !== -1) {
+                    throw newTranslatableError(hsResult.error);
+                }
+                throw newTranslatableError(_td("Unexpected error resolving homeserver configuration"));
+            } // else the error is not related to syntax - continue anyways.
         }
 
         const isResult = discoveryResult['m.identity_server'];
-        let preferredIdentityUrl = "https://vector.im";
+        let preferredIdentityUrl = "https://vector.im"; // We already know this is an IS, so don't validate it.
         if (isResult && isResult.state === AutoDiscovery.SUCCESS) {
             preferredIdentityUrl = isResult["base_url"];
         } else if (isResult && isResult.state !== AutoDiscovery.PROMPT) {
             console.error("Error determining preferred identity server URL:", isResult);
-            throw newTranslatableError(_td("Unexpected error resolving homeserver configuration"));
+            if (!syntaxOnly || !AutoDiscoveryUtils.isLivelinessError(isResult.error)) {
+                if (AutoDiscovery.ALL_ERRORS.indexOf(isResult.error) !== -1) {
+                    throw newTranslatableError(isResult.error);
+                }
+                throw newTranslatableError(_td("Unexpected error resolving identity server configuration"));
+            } // else the error is not related to syntax - continue anyways.
         }
 
         const preferredHomeserverUrl = hsResult["base_url"];