diff --git a/config/config.sample.yaml b/config/config.sample.yaml
index edb0b2e6994a21f6a89afdd6996173cfd7512a19..090b5998a5684d50189d87df721572613873abe9 100644
--- a/config/config.sample.yaml
+++ b/config/config.sample.yaml
@@ -38,6 +38,8 @@ bridge:
   disableInviteNotifications: false
   # Auto-determine the language of code blocks (this can be CPU-intensive)
   determineCodeLanguage: false
+  # MXID of an admin user that will be PMd if the bridge experiences problems. Optional
+  adminMxid: '@admin:localhost'
 # Authentication configuration for the discord bot.
 auth:
   # This MUST be a string (wrapped in quotes)
@@ -113,4 +115,4 @@ ghosts:
 metrics:
     enable: false
     port: 9001
-    host: "127.0.0.1"
\ No newline at end of file
+    host: "127.0.0.1"
diff --git a/src/config.ts b/src/config.ts
index 216d531eaa23879c7c74a0d2bfe4e3376624f2af..772e73092a66e77f324e375eb592b1139eccfdb4 100644
--- a/src/config.ts
+++ b/src/config.ts
@@ -100,6 +100,7 @@ class DiscordBridgeConfigBridge {
     public determineCodeLanguage: boolean = false;
     public activityTracker: UserActivityTrackerConfig = UserActivityTrackerConfig.DEFAULT;
     public userLimit: number|null = null;
+    public adminMxid: string|null = null;
 }
 
 export class DiscordBridgeConfigDatabase {
diff --git a/src/discordas.ts b/src/discordas.ts
index 182b5cda54906345b24e78652148f82c1fc8d978..49c65c1a4c5e638d810247a4b6ae99d57efc599c 100644
--- a/src/discordas.ts
+++ b/src/discordas.ts
@@ -13,7 +13,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 */
-import { Appservice, IAppserviceRegistration, LogService } from "matrix-bot-sdk";
+import { Appservice, IAppserviceRegistration, LogService, MatrixClient } from "matrix-bot-sdk";
 import * as yaml from "js-yaml";
 import * as fs from "fs";
 import { DiscordBridgeConfig } from "./config";
@@ -30,6 +30,8 @@ import { Response } from "express";
 
 const log = new Log("DiscordAS");
 
+const ADMIN_ROOMS_KEY = 'uk.half-shot.discord.admin-rooms';
+
 const commandOptions = [
     { name: "config", alias: "c", type: String },
     { name: "url", alias: "u", type: String },
@@ -215,7 +217,7 @@ async function run(): Promise<void> {
     roomhandler.bindThirdparty();
 
     try {
-        await startDiscordBot(discordbot);
+        await startDiscordBot(discordbot, appservice.botClient, config.bridge.adminMxid);
         log.info("Discordbot started successfully");
     } catch (err) {
         log.error(err);
@@ -228,16 +230,49 @@ async function run(): Promise<void> {
 
 }
 
-async function startDiscordBot(discordbot: DiscordBot, falloffSeconds = 5) {
+interface AdminRooms {
+    [mxid: string]: string;
+}
+
+async function notifyBridgeAdmin(client: MatrixClient, adminMxid: string, message: string) {
+    log.verbose(`Looking up admin room for ${adminMxid}`);
+    let adminRooms = await client.getAccountData<AdminRooms>(ADMIN_ROOMS_KEY).catch(() => null) || {};
+    if (!adminRooms[adminMxid]) {
+        log.verbose(`Creating an admin room for ${adminMxid}`);
+        adminRooms[adminMxid] = await client.createRoom();
+        await client.inviteUser(adminMxid, adminRooms[adminMxid]);
+        await client.setAccountData(ADMIN_ROOMS_KEY, adminRooms);
+    }
+    await client.sendText(adminRooms[adminMxid], message)
+}
+
+let adminNotified = false;
+
+async function startDiscordBot(
+    discordbot: DiscordBot,
+    client: MatrixClient,
+    adminMxid: string|null,
+    falloffSeconds = 5
+) {
     try {
         await discordbot.init();
         await discordbot.run();
     } catch (err) {
+        if (err.code === 'TOKEN_INVALID' && adminMxid && !adminNotified) {
+            await notifyBridgeAdmin(client, adminMxid, `Your Discord bot token seems to be invalid, and the bridge cannot function. Please update it in your bridge settings and restart the bridge`);
+            adminNotified = true;
+        }
+
         // no more than 5 minutes
         const newFalloffSeconds = Math.min(falloffSeconds * 2, 5 * 60);
         log.error(`Failed do start Discordbot: ${err.code}. Will try again in ${newFalloffSeconds} seconds`);
         await new Promise((r, _) => setTimeout(r, newFalloffSeconds * 1000));
-        return startDiscordBot(discordbot, newFalloffSeconds);
+        return startDiscordBot(discordbot, client, adminMxid, newFalloffSeconds);
+    }
+
+    if (adminMxid && adminNotified) {
+        await notifyBridgeAdmin(client, adminMxid, `The token situation is now resolved and the bridge is running correctly`);
+        adminNotified = false;
     }
 }