Index: protocols/Makefile
===================================================================
--- protocols/Makefile	(revision 9f03c472fef309878ff2f3bc720d51e6d03077f1)
+++ protocols/Makefile	(revision b4f496e7e9a22768f76c13b96deb1997bab55414)
@@ -13,5 +13,5 @@
 
 # [SH] Program variables
-objects = account.o bee.o bee_chat.o bee_ft.o bee_user.o nogaim.o
+objects = account.o bee.o bee_chat.o bee_ft.o bee_user.o nogaim.o unknown.o 
 
 
Index: protocols/nogaim.c
===================================================================
--- protocols/nogaim.c	(revision 9f03c472fef309878ff2f3bc720d51e6d03077f1)
+++ protocols/nogaim.c	(revision b4f496e7e9a22768f76c13b96deb1997bab55414)
@@ -160,4 +160,5 @@
 GList *protocols = NULL;
 GList *disabled_protocols = NULL;
+static struct prpl *unknown_prpl;
 
 void register_protocol(struct prpl *p)
@@ -191,7 +192,53 @@
 }
 
+struct prpl *make_unknown_protocol(const char *name)
+{
+	struct prpl *ret = g_memdup(unknown_prpl, sizeof(struct prpl));
+	ret->name = g_strdup(name);
+	register_protocol(ret);
+	return ret;
+}
+
 gboolean is_protocol_disabled(const char *name)
 {
 	return g_list_find_custom(disabled_protocols, name, proto_name_cmp) != NULL;
+}
+
+/* Returns heap allocated string with text attempting to explain why a protocol is missing 
+ * Free the return value with g_free() */
+char *explain_unknown_protocol(const char *name)
+{
+	char *extramsg = NULL;
+
+	if (is_protocol_disabled(name)) {
+		return g_strdup("Protocol disabled in the global config (bitlbee.conf)");
+	}
+
+	if (strcmp(name, "yahoo") == 0) {
+		return g_strdup("The old yahoo protocol is gone, try the funyahoo++ libpurple plugin instead.");
+	}
+
+#ifdef WITH_PURPLE
+	if ((strcmp(name, "msn") == 0) ||
+	    (strcmp(name, "loubserp-mxit") == 0) ||
+	    (strcmp(name, "myspace") == 0)) {
+		return g_strdup("This protocol has been removed from your libpurple version.");
+	}
+
+	if (strcmp(name, "hipchat") == 0) {
+		return g_strdup("This account type isn't supported by libpurple's jabber.");
+	}
+
+#else
+	if (strcmp(name, "aim") == 0 || strcmp(name, "icq") == 0) {
+		return g_strdup("This account uses libpurple specific aliases for oscar. "
+		                "Re-add the account with `account add oscar ...'");
+	}
+
+	extramsg = "If this is a libpurple plugin, you might need to install bitlbee-libpurple instead.";
+#endif
+	return g_strconcat("The protocol plugin is not installed or could not be loaded. "
+	                   "Use the `plugins' command to list available protocols. ",
+	                   extramsg, NULL);
 }
 
@@ -204,4 +251,7 @@
 	extern void twitter_initmodule();
 	extern void purple_initmodule();
+	extern void unknown_prpl_initmodule();
+
+	unknown_prpl_initmodule(&unknown_prpl);
 
 #ifdef WITH_MSN
Index: protocols/nogaim.h
===================================================================
--- protocols/nogaim.h	(revision 9f03c472fef309878ff2f3bc720d51e6d03077f1)
+++ protocols/nogaim.h	(revision b4f496e7e9a22768f76c13b96deb1997bab55414)
@@ -159,4 +159,7 @@
 	/* The protocol is not suitable for OTR, see OPT_NOOTR */
 	PRPL_OPT_NOOTR = 1 << 12,
+
+	/* This prpl is a placeholder for a missing protocol */
+	PRPL_OPT_UNKNOWN_PROTOCOL = 1 << 13,
 } prpl_options_t;
 
@@ -321,4 +324,6 @@
 G_MODULE_EXPORT struct prpl *find_protocol(const char *name);
 G_MODULE_EXPORT gboolean is_protocol_disabled(const char *name);
+G_MODULE_EXPORT struct prpl *make_unknown_protocol(const char *name);
+G_MODULE_EXPORT char *explain_unknown_protocol(const char *name);
 /* When registering a new protocol, you should allocate space for a new prpl
  * struct, initialize it (set the function pointers to point to your
Index: root_commands.c
===================================================================
--- root_commands.c	(revision 9f03c472fef309878ff2f3bc720d51e6d03077f1)
+++ root_commands.c	(revision b4f496e7e9a22768f76c13b96deb1997bab55414)
@@ -439,9 +439,8 @@
 
 		if (prpl == NULL) {
-			if (is_protocol_disabled(cmd[2])) {
-				irc_rootmsg(irc, "Protocol disabled in global config");
-			} else {
-				irc_rootmsg(irc, "Unknown protocol");
-			}
+			char *msg = explain_unknown_protocol(cmd[2]);
+			irc_rootmsg(irc, "Unknown protocol");
+			irc_rootmsg(irc, msg);
+			g_free(msg);
 			return;
 		}
Index: storage_xml.c
===================================================================
--- storage_xml.c	(revision 9f03c472fef309878ff2f3bc720d51e6d03077f1)
+++ storage_xml.c	(revision b4f496e7e9a22768f76c13b96deb1997bab55414)
@@ -60,5 +60,5 @@
 }
 
-static void handle_settings(struct xt_node *node, set_t **head)
+static void handle_settings(struct xt_node *node, set_t **head, gboolean add_unknowns)
 {
 	struct xt_node *c;
@@ -70,4 +70,11 @@
 
 		if (!name) {
+			continue;
+		}
+
+		if (add_unknowns && !set_find(head, name)) {
+			s = set_add(head, name, NULL, NULL, NULL);
+			s->flags |= ACC_SET_ONLINE_ONLY;
+			s->value = g_strdup(c->text);
 			continue;
 		}
@@ -99,4 +106,5 @@
 	account_t *acc;
 	struct xt_node *c;
+	gboolean is_unknown = FALSE;
 
 	handle = xt_find_attr(node, "handle");
@@ -111,7 +119,8 @@
 		prpl = find_protocol(protocol);
 		if (!prpl) {
-			irc_rootmsg(xd->irc, "Error loading user config: Protocol not found: `%s'", protocol);
-			return XT_ABORT;
-		}
+			irc_rootmsg(xd->irc, "Warning: Protocol not found: `%s'", protocol);
+			prpl = make_unknown_protocol(protocol);
+		}
+		is_unknown = (prpl->options & PRPL_OPT_UNKNOWN_PROTOCOL) != 0;
 		local = protocol_account_islocal(protocol);
 	}
@@ -153,5 +162,5 @@
 	g_free(password);
 
-	handle_settings(node, &acc->set);
+	handle_settings(node, &acc->set, is_unknown);
 
 	for (c = node->children; (c = xt_find_node(c, "buddy")); c = c->next) {
@@ -192,5 +201,5 @@
 	}
 
-	handle_settings(node, &ic->set);
+	handle_settings(node, &ic->set, FALSE);
 
 	return XT_HANDLED;
@@ -270,5 +279,5 @@
 	}
 
-	handle_settings(node, &xd->irc->b->set);
+	handle_settings(node, &xd->irc->b->set, FALSE);
 
 error:
