diff --git a/src/mpgame/bots/Bot.cpp b/src/mpgame/bots/Bot.cpp
--- a/src/mpgame/bots/Bot.cpp
+++ b/src/mpgame/bots/Bot.cpp
@@ -45,10 +45,35 @@ rvmBot::rvmBot()
 */
 rvmBot::~rvmBot()
 {
+	ReleaseBotResources();
 	gameLocal.UnRegisterBot( this );
 }
 
 /*
+===================
+rvmBot::ReleaseBotResources
+===================
+*/
+void rvmBot::ReleaseBotResources( void )
+{
+	if( bs.gs > 0 )
+	{
+		botGoalManager.BotFreeGoalState( bs.gs );
+		bs.gs = 0;
+	}
+
+	if( bs.ws > 0 )
+	{
+		botWeaponInfoManager.BotFreeWeaponState( bs.ws );
+		bs.ws = 0;
+	}
+
+	// Character profiles are shared cache entries owned by their manager.
+	bs.character = NULL;
+	hasSpawned = false;
+}
+
+/*
 ==================
 rvmBot::SetEnemy
 ==================
@@ -180,32 +205,45 @@ void rvmBot::Spawn( void )
 		}
 		if( !bs.character )
 		{
+			ReleaseBotResources();
 			gameLocal.Error( "Failed to load character file for bot %s\n", botName.c_str() );
+			return;
 		}
 
 		// Allocate the goal state.
 		bs.gs = botGoalManager.BotAllocGoalState( entityNumber );
+		if( bs.gs <= 0 )
+		{
+			ReleaseBotResources();
+			gameLocal.Error( "Failed to allocate goal state for bot %s\n", botName.c_str() );
+			return;
+		}
 
 		// Get the bot items weights file name.
 		botCharacterStatsManager.Characteristic_String( bs.character, CHARACTERISTIC_ITEMWEIGHTS, filename, 256 );
 		errnum = botGoalManager.BotLoadItemWeights( bs.gs, filename );
 		if( errnum != BLERR_NOERROR )
 		{
+			ReleaseBotResources();
 			gameLocal.Error( "Failed to load bot item weights!" );
-			botGoalManager.BotFreeGoalState( bs.gs );
 			return;
 		}
 
 		//allocate a weapon state
 		bs.ws = botWeaponInfoManager.BotAllocWeaponState();
+		if( bs.ws <= 0 )
+		{
+			ReleaseBotResources();
+			gameLocal.Error( "Failed to allocate weapon state for bot %s\n", botName.c_str() );
+			return;
+		}
 
 		//load the weapon weights
 		botCharacterStatsManager.Characteristic_String( bs.character, CHARACTERISTIC_WEAPONWEIGHTS, filename, 256 );
 		errnum = botWeaponInfoManager.BotLoadWeaponWeights( bs.ws, filename );
 		if( errnum != BLERR_NOERROR )
 		{
-			//	trap_BotFreeGoalState(bs->gs);
-			botWeaponInfoManager.BotFreeWeaponState( bs.ws );
+			ReleaseBotResources();
 			return;
 		}
 
diff --git a/src/mpgame/bots/Bot.h b/src/mpgame/bots/Bot.h
--- a/src/mpgame/bots/Bot.h
+++ b/src/mpgame/bots/Bot.h
@@ -861,6 +861,7 @@ public:
 
 	static void		PresenceTypeBoundingBox( int presencetype, idVec3& mins, idVec3& maxs );
 private:
+	void			ReleaseBotResources( void );
 	void			BotSendChatMessage(botChat_t chat, const char *targetName);
 
 	void			BotInputToUserCommand( bot_input_t* bi, usercmd_t* ucmd, int time );
diff --git a/src/mpgame/bots/Bot_weapons.cpp b/src/mpgame/bots/Bot_weapons.cpp
--- a/src/mpgame/bots/Bot_weapons.cpp
+++ b/src/mpgame/bots/Bot_weapons.cpp
@@ -34,7 +34,14 @@ bot_weaponstate_t* idBotWeaponInfoManager::BotWeaponStateFromHandle( int handle
 {
 	if( handle <= 0 || handle > MAX_CLIENTS )
 	{
-		gameLocal.Error( "move state handle %d out of range\n", handle );
+		gameLocal.Error( "weapon state handle %d out of range\n", handle );
+		return NULL;
+	}
+
+	if( !botweaponstates[handle].inUse )
+	{
+		gameLocal.Error( "invalid weapon state handle %d\n", handle );
+		return NULL;
 	}
 
 	return &botweaponstates[handle];
@@ -334,9 +341,12 @@ void idBotWeaponInfoManager::BotFreeWeaponWeights( int weaponstate )
 	{
 		return;
 	}
-//	if (ws->weaponweightconfig)
-//		FreeWeightConfig(ws->weaponweightconfig);
-	//	if (ws->weaponweightindex) FreeMemory(ws->weaponweightindex);
+	if( ws->weaponweightconfig )
+	{
+		botFuzzyWeightManager.FreeWeightConfig( ws->weaponweightconfig );
+		ws->weaponweightconfig = NULL;
+	}
+	memset( ws->weaponweightindex, 0, sizeof( ws->weaponweightindex ) );
 }
 
 /*
@@ -487,6 +497,12 @@ int idBotWeaponInfoManager::BotAllocWeaponState( void )
 */
 void idBotWeaponInfoManager::BotFreeWeaponState( int ws )
 {
-	botweaponstates[ws].inUse = false;
-	botweaponstates[ws].Reset();
+	bot_weaponstate_t* weaponState = BotWeaponStateFromHandle( ws );
+	if( !weaponState )
+	{
+		return;
+	}
+
+	BotFreeWeaponWeights( ws );
+	weaponState->Reset();
 }
diff --git a/src/mpgame/bots/Bot_weights.cpp b/src/mpgame/bots/Bot_weights.cpp
--- a/src/mpgame/bots/Bot_weights.cpp
+++ b/src/mpgame/bots/Bot_weights.cpp
@@ -189,10 +189,13 @@ void idBotFuzzyWeightManager::FreeWeightConfig( weightconfig_t* config )
 */
 void idBotFuzzyWeightManager::FreeWeightConfig( weightconfig_t* config )
 {
-	//if (!LibVarGetValue("bot_reloadcharacters"))
-	//	return;
+	if( !config )
+	{
+		return;
+	}
 
 	FreeWeightConfig2( config );
+	config->Reset();
 }
 
 /*
