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

  1. Ensure POST /start (reset) completes and the bot connects before any /pause call — sequence your client to await the spawn.
  2. Do not call /pause after /stop; track lifecycle state client-side.
  3. If the Minecraft server was unavailable at start, restart the bridge and re-run /start.
  4. 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

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


AI-assisted analysis of FoundationAgents/MetaGPT@11cdf466d0 (2026-08-14). Data as JSON: /api/errors/1d7dd0b813f14d45. Report an issue: GitHub.