Summary
ensureDockerImage() in dist/reply-Bm8VrLQh.js has a hardcoded fallback that runs docker tag debian:bookworm-slim openclaw-sandbox:bookworm-slim whenever the sandbox image is missing. This silently replaces any custom-built image (with python3, jq, ripgrep, etc.) with plain debian — breaking Write/Edit tools that depend on python3.
This is the root cause behind #45108, #51099, and partially #24151.
Mechanism
async function ensureDockerImage(image) {
if (await dockerImageExists(image)) return;
if (image === "openclaw-sandbox:bookworm-slim") {
await execDocker(["pull", "debian:bookworm-slim"]);
await execDocker(["tag", "debian:bookworm-slim", DEFAULT_SANDBOX_IMAGE]);
return;
}
throw new Error(`Sandbox image not found`);
}
The function checks if the image exists. If not, it pulls debian:bookworm-slim and tags it directly — without checking for a local Dockerfile (e.g., scripts/Dockerfile.sandbox).
Reproduction
- Build a custom sandbox image:
docker build -t openclaw-sandbox:bookworm-slim -f scripts/Dockerfile.sandbox scripts/
- Verify:
docker run --rm openclaw-sandbox:bookworm-slim python3 --version → Python 3.11.2
- Remove the image:
docker rmi openclaw-sandbox:bookworm-slim
- Send any message via Telegram (triggers sandbox creation)
- Verify:
docker inspect openclaw-sandbox:bookworm-slim --format '{{.Id}}' matches debian:bookworm-slim — same image ID, no python3
This happens after any docker system prune, docker image prune, or manual image removal.
Expected behavior
ensureDockerImage() should check for a user-provided Dockerfile before falling back to tagging plain debian:
async function ensureDockerImage(image) {
if (await dockerImageExists(image)) return;
if (image === "openclaw-sandbox:bookworm-slim") {
const dockerfilePath = path.join(projectRoot, "scripts/Dockerfile.sandbox");
if (await fileExists(dockerfilePath)) {
await execDocker(["build", "-t", DEFAULT_SANDBOX_IMAGE, "-f", dockerfilePath, path.dirname(dockerfilePath)]);
return;
}
await execDocker(["pull", "debian:bookworm-slim"]);
await execDocker(["tag", "debian:bookworm-slim", DEFAULT_SANDBOX_IMAGE]);
return;
}
throw new Error(`Sandbox image not found`);
}
Or alternatively, support a sandbox.docker.buildFile config key that points to the Dockerfile.
Impact
- Write/Edit tools break silently (python3 not found)
- Agents fall back to
exec with heredoc (unreliable workaround)
- Users must manually rebuild the image after every prune — with no warning that it was overwritten
Related issues
Environment
- openclaw v2026.3.13
- macOS (Darwin 25.3.0, arm64)
- Docker Desktop
Summary
ensureDockerImage()indist/reply-Bm8VrLQh.jshas a hardcoded fallback that runsdocker tag debian:bookworm-slim openclaw-sandbox:bookworm-slimwhenever the sandbox image is missing. This silently replaces any custom-built image (with python3, jq, ripgrep, etc.) with plain debian — breaking Write/Edit tools that depend on python3.This is the root cause behind #45108, #51099, and partially #24151.
Mechanism
The function checks if the image exists. If not, it pulls
debian:bookworm-slimand tags it directly — without checking for a local Dockerfile (e.g.,scripts/Dockerfile.sandbox).Reproduction
docker build -t openclaw-sandbox:bookworm-slim -f scripts/Dockerfile.sandbox scripts/docker run --rm openclaw-sandbox:bookworm-slim python3 --version→Python 3.11.2docker rmi openclaw-sandbox:bookworm-slimdocker inspect openclaw-sandbox:bookworm-slim --format '{{.Id}}'matchesdebian:bookworm-slim— same image ID, no python3This happens after any
docker system prune,docker image prune, or manual image removal.Expected behavior
ensureDockerImage()should check for a user-provided Dockerfile before falling back to tagging plain debian:Or alternatively, support a
sandbox.docker.buildFileconfig key that points to the Dockerfile.Impact
execwith heredoc (unreliable workaround)Related issues
docker.imageconfig ignoredEnvironment