{"record":{"id":"df55e8222f2a47dc","repo":"langchain-ai/deepagents","slug":"blueprint-blueprint-name-exists-but-its-last-b","errorCode":null,"errorMessage":"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.","messagePattern":"Blueprint '(.+?)' exists but its last build failed\\. Delete it and retry, or fix the Dockerfile\\. \\| Blueprint '(.+?)' exists but is still building \\(state '(.+?)'\\)\\. Wait for it to finish, or delete it to rebuild\\.","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"libs/partners/runloop/langchain_runloop/provider.py","lineNumber":111,"sourceCode":"        try:\n            page = client.blueprints.list(**list_kwargs)\n        except Exception as e:\n            msg = f\"Failed to list blueprints: {e}\"\n            raise RuntimeError(msg) from e\n\n        for blueprint in page.blueprints:\n            if blueprint.name != blueprint_name:\n                continue\n            if blueprint.status == \"build_complete\":\n                return\n            non_ready_status = blueprint.status\n\n        if not page.has_more or not page.blueprints:\n            break\n        starting_after = page.blueprints[-1].id\n\n    if non_ready_status is not None:\n        raise RuntimeError(_not_ready_message(blueprint_name, non_ready_status))\n\n    try:\n        client.blueprints.create_and_await_build_complete(\n            name=blueprint_name,\n            dockerfile=dockerfile,\n        )\n    except Exception as create_err:\n        msg = f\"Failed to build blueprint '{blueprint_name}': {create_err}\"\n        raise RuntimeError(msg) from create_err\n\n\nclass RunloopProvider:\n    \"\"\"Create or attach Runloop devboxes, optionally from named blueprints.\"\"\"\n\n    def __init__(\n        self,\n        *,\n        api_key: str,","sourceCodeStart":93,"sourceCodeEnd":129,"githubUrl":"https://github.com/langchain-ai/deepagents/blob/a1af029e6e73cb17c36bff823d227747b28e91e1/libs/partners/runloop/langchain_runloop/provider.py#L93-L129","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nsandbox = provider.get_or_create(snapshot=\"my-bp\")  # RuntimeError: still building\n\n// after\nimport time\ntry:\n    sandbox = provider.get_or_create(snapshot=\"my-bp\")\nexcept RuntimeError as e:\n    if \"still building\" in str(e):\n        time.sleep(60)\n        sandbox = provider.get_or_create(snapshot=\"my-bp\")\n    elif \"last build failed\" in str(e):\n        client.blueprints.delete(name=\"my-bp\")  # then retry\n        sandbox = provider.get_or_create(snapshot=\"my-bp\")","handlingStrategy":"retry","validationCode":"import time\n\ndef wait_until_blueprint_ready(client, name, timeout_s=600):\n    deadline = time.time() + timeout_s\n    while time.time() < deadline:\n        status = get_blueprint_status(client, name)  # paginated list by name\n        if status == \"build_complete\":\n            return True\n        if status == \"failed\":\n            return False\n        time.sleep(10)\n    return False","typeGuard":"def is_blueprint_ready(status: str | None) -> bool:\n    return status == \"build_complete\"","tryCatchPattern":"try:\n    sandbox = provider.get_or_create(snapshot=\"my-bp\")\nexcept RuntimeError as e:\n    if \"last build failed\" in str(e):\n        delete_blueprint(\"my-bp\")  # then rebuild once\n        sandbox = provider.get_or_create(snapshot=\"my-bp\")\n    elif \"still building\" in str(e):\n        time.sleep(60)  # poll until ready, then retry\n    else:\n        raise","preventionTips":["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=`."],"tags":["runloop","blueprint","build-failed","dockerfile"],"backgroundTag":"blueprint-build-not-ready","analyzedSha":"a1af029e6e73cb17c36bff823d227747b28e91e1","analyzedAt":"2026-08-29T11:43:24.718Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}