What you will build
This lesson submits one spawnCreep() request for a fixed beginner Creep named Worker1. The body is [WORK, CARRY, MOVE], which costs 200 Energy. You will check the method return code, then distinguish “request accepted” from “Creep finished spawning.”
Game mode boundary
This guide covers Screeps World/MMO, where StructureSpawn.spawnCreep(body, name, opts) is the relevant contract. Screeps Arena uses a different spawnCreep(body) contract. If you are playing Arena, use the dedicated Screeps Arena spawnCreep guide.
Before you start
You need a Spawn you own and a room with enough currently available Energy for the selected body. This example expects Game.spawns.Spawn1; change the name if your Spawn has another name.
const spawn = Game.spawns.Spawn1;
if (!spawn) {
console.log('Spawn1 was not found.');
}
Do not call methods on an undefined Spawn. A missing object is a JavaScript problem before it is a Screeps API problem.
Use a body your room can afford
The beginner body has three parts:
| Part | Energy cost | Purpose here |
|---|---|---|
WORK | 100 | Harvest or perform WORK-based tasks later |
CARRY | 50 | Carry Energy |
MOVE | 50 | Move the Creep |
Total: 200 Energy. This is a learning body, not a universal production design.
Minimal working example
module.exports.loop = function () {
const spawn = Game.spawns.Spawn1;
if (!spawn) {
return;
}
if (Game.creeps.Worker1 || spawn.spawning) {
return;
}
const result = spawn.spawnCreep(
[WORK, CARRY, MOVE],
'Worker1',
{
memory: {
role: 'worker'
}
}
);
if (result !== OK) {
console.log('spawnCreep() returned ' + result);
}
};
The fixed name makes the first request easy to understand. The guard prevents the loop from intentionally submitting the same fixed-name request while Worker1 already exists or this Spawn is busy.
Read the return code
The current official spawnCreep() return boundary includes:
| Result | Meaning | What to check |
|---|---|---|
OK | The request was accepted. | Observe spawning state on later ticks. |
ERR_NOT_OWNER | The Spawn is not yours. | Select a player-owned Spawn. |
ERR_NAME_EXISTS | The Creep name is already in use. | Use a unique name or recognize the existing Creep. |
ERR_BUSY | The Spawn is already spawning. | Wait for spawn.spawning to clear. |
ERR_NOT_ENOUGH_ENERGY | The room does not currently have enough available spawn Energy. | Reduce the body or wait for available Energy. |
ERR_INVALID_ARGS | The body, name, or request arguments are invalid. | Validate body constants and the name. |
ERR_RCL_NOT_ENOUGH | The current Room Controller level is insufficient to use this Spawn. | Check the room Controller level and whether spawn.isActive() is true. |
For a diagnostic page centered on the full return-code workflow, continue with spawnCreep() return codes. This beginner page stays focused on the first safe request.
OK is not the same as finished
A successful call starts a process. Screeps uses CREEP_SPAWN_TIME = 3 ticks per body part. A three-part body therefore has 9 ticks of spawn time.
if (spawn.spawning) {
console.log(JSON.stringify({
tick: Game.time,
name: spawn.spawning.name,
remainingTime: spawn.spawning.remainingTime,
needTime: spawn.spawning.needTime
}));
}
Do not invent a completion tick from an article example. Read the current spawning state. When the Creep object is available, check its own spawning state before expecting normal actions.
Use dryRun for diagnostics
dryRun: true checks the request without starting the spawn process:
const check = spawn.spawnCreep(
[WORK, CARRY, MOVE],
'Worker1',
{
dryRun: true,
memory: { role: 'worker' }
}
);
console.log('dryRun returned ' + check);
A dry run is useful before a complex request, but it is not a reservation. State can change before the real call, so production code must still check the actual return code.
What to verify next
After you run the example in a room you control, verify these observations yourself:
- The initial real request returns
OK. spawn.spawningreports the active Creep name while the Spawn is busy.- The spawn process lasts according to the body-part timing shown by the live spawning object.
- After spawning completes,
Worker1is available for normal role logic and its initializedmemory.roleis readable.
This editorial pass did not run that live sequence, so both Console and live multi-tick verification remain pending.
Production adaptation
The fixed name and fixed body are teaching constraints. A production spawn manager normally separates four decisions:
- How many Creeps of each role should exist?
- Which body fits current Energy and the role's job?
- Which unique name and initial Memory should be assigned?
- Which Spawn should receive the request, and what should happen after each return code?
Use dynamic body sizing when the body should scale with Energy, and keep queue/replacement logic out of this first-request example.
Common failures
- Calling
spawnCreep()on an undefined Spawn. - Ignoring
ERR_BUSYand resubmitting while the Spawn is occupied. - Using the same fixed name without checking whether that Creep already exists.
- Designing a body that costs more than current available spawn Energy.
- Treating
OKas “the Creep is already finished.” - Calling a dry run and assuming the later real request cannot fail.
- Adding production queue complexity before the first API boundary is understood.
Next lesson
Once one Creep can be spawned and identified safely, continue with Screeps Memory to understand persistent role/state data, then use the dedicated return-code guide when you add production retry policy.
Frequently asked questions
What does spawnCreep() returning OK mean?
The request was accepted. Spawning still takes time; inspect spawn.spawning and later Creep state.
How much does [WORK, CARRY, MOVE] cost?
200 Energy: 100 + 50 + 50.
How long does a three-part Creep take?
With the official 3 ticks per body part constant, the body requires 9 spawn ticks. Use the live spawning object to observe the actual process.
Is dryRun enough for production?
No. It validates a request at that moment without spawning; the real call still needs its own return-code handling.