langchain-ai/deepagents · error · RuntimeError
Blueprint '{blueprint_name}' exists but its last build faile
Error message
Blueprint '{blueprint_name}' exists but its last build failed. Delete it and retry, or fix the Dockerfile. | Blueprint '{blueprint_name}' exists but is still building (state '{status}'). Wait for it to finish, or delete it to rebuild. What it means
Raised by `_ensure_blueprint` when a blueprint with the requested name exists in Runloop but its status is not `build_complete`. A `failed` status is terminal so the message advises deleting it or fixing the Dockerfile; any other non-complete status (`queued`, `provisioning`, `building`) means the build is still in flight and the caller should wait or delete to rebuild. The function intentionally refuses to create a duplicate or block indefinitely on a same-name blueprint.
Source
Thrown at libs/partners/runloop/langchain_runloop/provider.py:111
try:
page = client.blueprints.list(**list_kwargs)
except Exception as e:
msg = f"Failed to list blueprints: {e}"
raise RuntimeError(msg) from e
for blueprint in page.blueprints:
if blueprint.name != blueprint_name:
continue
if blueprint.status == "build_complete":
return
non_ready_status = blueprint.status
if not page.has_more or not page.blueprints:
break
starting_after = page.blueprints[-1].id
if non_ready_status is not None:
raise RuntimeError(_not_ready_message(blueprint_name, non_ready_status))
try:
client.blueprints.create_and_await_build_complete(
name=blueprint_name,
dockerfile=dockerfile,
)
except Exception as create_err:
msg = f"Failed to build blueprint '{blueprint_name}': {create_err}"
raise RuntimeError(msg) from create_err
class RunloopProvider:
"""Create or attach Runloop devboxes, optionally from named blueprints."""
def __init__(
self,
*,
api_key: str,View on GitHub (pinned to a1af029e6e)
Solutions
- Check the blueprint status in the Runloop dashboard; if still building, wait and retry later.
- If status is `failed`, delete the blueprint (API or dashboard) and retry so `_ensure_blueprint` rebuilds it.
- Fix the Dockerfile (e.g. pass `blueprint_dockerfile=` with a working Dockerfile) before deleting and rebuilding.
- Alternatively boot by blueprint ID instead: set `RUNLOOP_SANDBOX_BLUEPRINT_ID`, which skips the name-based ensure path entirely.
- Or unset `snapshot`/`RUNLOOP_SANDBOX_BLUEPRINT_NAME` to create a plain empty devbox.
Example fix
// before
sandbox = provider.get_or_create(snapshot="my-bp") # RuntimeError: still building
// after
import time
try:
sandbox = provider.get_or_create(snapshot="my-bp")
except RuntimeError as e:
if "still building" in str(e):
time.sleep(60)
sandbox = provider.get_or_create(snapshot="my-bp")
elif "last build failed" in str(e):
client.blueprints.delete(name="my-bp") # then retry
sandbox = provider.get_or_create(snapshot="my-bp") Defensive patterns
Strategy: retry
Validate before calling
import time
def wait_until_blueprint_ready(client, name, timeout_s=600):
deadline = time.time() + timeout_s
while time.time() < deadline:
status = get_blueprint_status(client, name) # paginated list by name
if status == "build_complete":
return True
if status == "failed":
return False
time.sleep(10)
return False Type guard
def is_blueprint_ready(status: str | None) -> bool:
return status == "build_complete" Try / catch
try:
sandbox = provider.get_or_create(snapshot="my-bp")
except RuntimeError as e:
if "last build failed" in str(e):
delete_blueprint("my-bp") # then rebuild once
sandbox = provider.get_or_create(snapshot="my-bp")
elif "still building" in str(e):
time.sleep(60) # poll until ready, then retry
else:
raise Prevention
- Poll blueprint status before creating devboxes from it.
- Delete failed blueprints as part of CI cleanup so stale `failed` states don't block rebuilds.
- Prefer blueprint ID env (`RUNLOOP_SANDBOX_BLUEPRINT_ID`) for known-good blueprints to skip the name-based path.
- Keep a verified Dockerfile in version control and pass it via `blueprint_dockerfile=`.
When it happens
Trigger: Calling `RunloopProvider.get_or_create` (directly or via `snapshot=` or `RUNLOOP_SANDBOX_BLUEPRINT_NAME`) when the named blueprint exists with status `failed`, `queued`, `provisioning`, or `building` after `_ensure_blueprint` paginates through `client.blueprints.list(name=..., limit=100)` without finding a `build_complete` match.
Common situations: A previous build of the blueprint failed due to a bad Dockerfile; a CI job or teammate kicked off a rebuild that is still running; a stale failed blueprint from an earlier experiment shares the name.
Related errors
- Failed to build blueprint '{blueprint_name}': {create_err}
- Failed to list blueprints: {e}
- Blueprint name is required when no blueprint ID is set
- {sandbox_id}
- Runloop rejected the credentials; check RUNLOOP_API_KEY (or
AI-assisted analysis of langchain-ai/deepagents@a1af029e6e (2026-08-29).
Data as JSON: /api/errors/df55e8222f2a47dc.
Report an issue: GitHub.