FoundationAgents/MetaGPT · warning
Bot not spawned
Error message
Bot not spawned
What it means
This is an HTTP 400 error from the mineflayer Express bridge's POST /pause endpoint, returned when the module-level `bot` variable is falsy — i.e. no bot has spawned/connect yet. The pause route must send bot.chat('/pause'), which requires a live bot; endpoints like /pause and /unpause check for the bot first and reject early.
Source
Thrown at metagpt/environment/minecraft/mineflayer/index.js:410
.split("\n")
[match_line - 1].trim()} in your code`;
}
return source + err.message + "\n" + code_source;
}
return err.message;
}
});
app.post("/stop", (req, res) => {
bot.end();
res.json({
message: "Bot stopped",
});
});
app.post("/pause", (req, res) => {
if (!bot) {
res.status(400).json({ error: "Bot not spawned" });
return;
}
bot.chat("/pause");
bot.waitForTicks(bot.waitTicks).then(() => {
res.json({ message: "Success" });
});
});
// Server listening to PORT 3000
const DEFAULT_PORT = 3000;
const PORT = process.argv[2] || DEFAULT_PORT;
app.listen(PORT, () => {
console.log(`Server started on port ${PORT}`);
});
View on GitHub (pinned to 11cdf466d0)
Solutions
- Ensure POST /start (reset) completes and the bot connects before any /pause call — sequence your client to await the spawn.
- Do not call /pause after /stop; track lifecycle state client-side.
- If the Minecraft server was unavailable at start, restart the bridge and re-run /start.
- In your own forks, treat a 400 'Bot not spawned' as a benign no-op during shutdown instead of an error.
Example fix
// before (client)
await fetch(`${bridge}/pause`, {method: "POST"}); // 400 Bot not spawned
// after (client)
if (botSpawned) {
await fetch(`${bridge}/pause`, {method: "POST"});
}
// or in the route, make pause idempotent:
app.post("/pause", (req, res) => {
if (!bot) { res.json({ message: "No bot, nothing to pause" }); return; }
...
}); Defensive patterns
Strategy: validation
Validate before calling
// client-side: only pause when the bot was started in this session
let botAlive = false;
async function start() {
const r = await fetch(`${bridge}/start`, { method: "POST" });
botAlive = r.ok;
}
async function pause() {
if (!botAlive) return; // avoid 400 'Bot not spawned'
await fetch(`${bridge}/pause`, { method: "POST" });
} Try / catch
// server-side fork: treat pause without a bot as a no-op
app.post("/pause", (req, res) => {
if (!bot) { res.status(200).json({ message: "No bot spawned; nothing to pause" }); return; }
bot.chat("/pause");
bot.waitForTicks(bot.waitTicks).then(() => res.json({ message: "Success" }));
}); Prevention
- Track lifecycle client-side: /start succeeded => pause/unpause allowed; /stop or failed start => skip pause calls.
- Never call /pause during teardown after /stop.
- Wait for bot spawn (connect/spawn event) before the Python side's first reset-triggered pause.
When it happens
Trigger: Any client (including MinecraftExtEnv.pause(), which fires on every successful reset/step) calling POST /pause before /start has spawned the bot, or after the bot ended via /stop, or after a bot connection error left bot unset.
Common situations: Startup ordering races: the Python side calls reset/step machinery before the bot finished connecting to the Minecraft server; the Minecraft server was down so /start failed and later /pause hits the unspawned bot; calling /stop then /pause in cleanup code.
Related errors
- Environment has not been reset yet
- Failed to step Minecraft server
- SPO_LLM not initialized. Call initialize() first.
AI-assisted analysis of FoundationAgents/MetaGPT@11cdf466d0 (2026-08-14).
Data as JSON: /api/errors/1d7dd0b813f14d45.
Report an issue: GitHub.