Describe the bug
Every runtime.exec call against the container backend runs the literal string undefined instead of the caller's command, because the computerd image the example Dockerfiles pin predates the exec wire-field rename.
04b7f34 ("rpc, computer: rename the shell exec field to source", 2026-08-03) renamed ShellRPC.exec's field from command to source. The published image is 0.1.0-alpha.1, tagged by 48aa155 ("chore: tag v0.1.0-alpha.1") on 2026-07-30 β three days earlier. The binary inside it still reads input.command.
The host now sends source:
packages/computer/src/shell.ts:130 β this.#shell.exec({ source, id, cwd, timeoutMs, env, stdin })
packages/rpc/src/server.ts:251 β return this.runner.exec(input.source, { ... })
The pinned daemon reads input.command, gets undefined, and interpolates it into the shell string at packages/computerd/src/exec/runner.ts:144-145:
const wrapped = cwd !== undefined ? `cd ${shellQuote(cwd)} && ${command}` : command;
const child = spawn("/bin/sh", ["-c", wrapped], { ... });
so /bin/sh receives the four characters undefined as its command:
{"status":"failed","exitCode":127,"stdout":"","stderr":"/bin/sh: 1: undefined: not found\n",
"sync":{"status":"complete","applied":0,"skipped":[]}}
Note the failure is silent in shape: sync succeeds, the RPC round trip succeeds, and the error surfaces only as a shell "command not found" for a command the caller never wrote.
The stale pin appears in six places:
examples/container/Dockerfile:17
examples/think/Dockerfile:12
examples/tutorial/Dockerfile:11
examples/think-compare-runtimes/Dockerfile.workspace:15
docs/README.md:66
packages/computer-computerd-linux-x64/README.md:23
Related, and possibly a separate bug: examples/think-compare-runtimes has "predev": "npm run build:computerd", which builds the daemon from source β but packages/computerd/scripts/build-docker.mjs:28 tags it cloudflare/computer-computerd-linux-x64 (no registry prefix) while Dockerfile.workspace:15 consumes ghcr.io/cloudflare/.... The example builds a correct binary and then does not use it.
Prior art: #52's repro notes the reporter deployed examples/container "unmodified except for β¦ computerd tag bumped to 0.1.1", i.e. an independent reporter hit this and worked around it without filing. #59 documents a sibling wire-contract break from the same refactor family, and quotes docs/08:127-129 on the interface having no version negotiation ("hard wire breaks") β which is the policy this violates.
Expected behavior
runtime.exec(source, ...) against the container backend runs source. Either the examples pin an image whose computerd reads the same field name the host sends, or the wire mismatch is detected and reported as a protocol error rather than degrading into a shell "command not found".
Steps to reproduce
npm install at the repo root, then cd examples/container.
npx wrangler dev (Linux or WSL β containers are unsupported on Windows).
- Write a file, then exec:
curl -X PUT --data-binary "hello" http://127.0.0.1:8787/c/demo/file/workspace/hello.txt
curl -X POST http://127.0.0.1:8787/c/demo/exec \
-H 'content-type: application/json' -d '{"command":"echo EXEC_OK"}'
- Observed:
{"status":"failed","stderr":"/bin/sh: 1: undefined: not found\n", ...}. Expected: EXEC_OK on stdout.
The write/read path succeeds, so this is specific to exec.
Confirming the cause: building the daemon from source and making the example consume it makes the same request succeed:
npm run build:docker --workspace @cloudflare/computerd
docker tag cloudflare/computer-computerd-linux-x64:0.1.0-alpha.1 \
ghcr.io/cloudflare/computer-computerd-linux-x64:0.1.0-alpha.1
docker rmi -f $(docker images -q cloudflare-dev/containerexample) # else wrangler reuses the cached image
Re-running step 3 then returns {"status":"completed","exitCode":0,"stdout":"EXEC_OK\n"}.
The docker rmi matters: wrangler derives its image tag from the Dockerfile text, so retagging the base alone does not invalidate its cache and the old image is silently reused.
Proposed fix
Publish a computerd image built after 04b7f34 and bump the six pins, or move the examples onto the locally built image. .github/changeset-version.mjs:17 (added in PR #49) already rewrites these pins during the Version Packages PR, so the release machinery exists β it just has not run since the rename, and the currently published tag is broken for every example that uses the container backend.
Worth considering separately: packages/rpc could reject an exec payload with no source field instead of passing undefined through to spawn, so a future wire break surfaces as a protocol error rather than a shell error.
Environment
cloudflare/computer at 76d9e75 (current main)
- Ubuntu 24.04 under WSL2, Docker 29.1.3, wrangler 4.115.0, Node 22.22.1
examples/container, container backend via computerd 0.1.0-alpha.1
Describe the bug
Every
runtime.execcall against the container backend runs the literal stringundefinedinstead of the caller's command, because thecomputerdimage the example Dockerfiles pin predates the exec wire-field rename.04b7f34("rpc, computer: rename the shell exec field to source", 2026-08-03) renamedShellRPC.exec's field fromcommandtosource. The published image is0.1.0-alpha.1, tagged by48aa155("chore: tag v0.1.0-alpha.1") on 2026-07-30 β three days earlier. The binary inside it still readsinput.command.The host now sends
source:packages/computer/src/shell.ts:130βthis.#shell.exec({ source, id, cwd, timeoutMs, env, stdin })packages/rpc/src/server.ts:251βreturn this.runner.exec(input.source, { ... })The pinned daemon reads
input.command, getsundefined, and interpolates it into the shell string atpackages/computerd/src/exec/runner.ts:144-145:so
/bin/shreceives the four charactersundefinedas its command:{"status":"failed","exitCode":127,"stdout":"","stderr":"/bin/sh: 1: undefined: not found\n", "sync":{"status":"complete","applied":0,"skipped":[]}}Note the failure is silent in shape: sync succeeds, the RPC round trip succeeds, and the error surfaces only as a shell "command not found" for a command the caller never wrote.
The stale pin appears in six places:
examples/container/Dockerfile:17examples/think/Dockerfile:12examples/tutorial/Dockerfile:11examples/think-compare-runtimes/Dockerfile.workspace:15docs/README.md:66packages/computer-computerd-linux-x64/README.md:23Related, and possibly a separate bug:
examples/think-compare-runtimeshas"predev": "npm run build:computerd", which builds the daemon from source β butpackages/computerd/scripts/build-docker.mjs:28tags itcloudflare/computer-computerd-linux-x64(no registry prefix) whileDockerfile.workspace:15consumesghcr.io/cloudflare/.... The example builds a correct binary and then does not use it.Prior art: #52's repro notes the reporter deployed
examples/container"unmodified except for β¦ computerd tag bumped to0.1.1", i.e. an independent reporter hit this and worked around it without filing. #59 documents a sibling wire-contract break from the same refactor family, and quotesdocs/08:127-129on the interface having no version negotiation ("hard wire breaks") β which is the policy this violates.Expected behavior
runtime.exec(source, ...)against the container backend runssource. Either the examples pin an image whosecomputerdreads the same field name the host sends, or the wire mismatch is detected and reported as a protocol error rather than degrading into a shell "command not found".Steps to reproduce
npm installat the repo root, thencd examples/container.npx wrangler dev(Linux or WSL β containers are unsupported on Windows).{"status":"failed","stderr":"/bin/sh: 1: undefined: not found\n", ...}. Expected:EXEC_OKon stdout.The write/read path succeeds, so this is specific to exec.
Confirming the cause: building the daemon from source and making the example consume it makes the same request succeed:
npm run build:docker --workspace @cloudflare/computerd docker tag cloudflare/computer-computerd-linux-x64:0.1.0-alpha.1 \ ghcr.io/cloudflare/computer-computerd-linux-x64:0.1.0-alpha.1 docker rmi -f $(docker images -q cloudflare-dev/containerexample) # else wrangler reuses the cached imageRe-running step 3 then returns
{"status":"completed","exitCode":0,"stdout":"EXEC_OK\n"}.The
docker rmimatters: wrangler derives its image tag from the Dockerfile text, so retagging the base alone does not invalidate its cache and the old image is silently reused.Proposed fix
Publish a
computerdimage built after04b7f34and bump the six pins, or move the examples onto the locally built image..github/changeset-version.mjs:17(added in PR #49) already rewrites these pins during the Version Packages PR, so the release machinery exists β it just has not run since the rename, and the currently published tag is broken for every example that uses the container backend.Worth considering separately:
packages/rpccould reject anexecpayload with nosourcefield instead of passingundefinedthrough tospawn, so a future wire break surfaces as a protocol error rather than a shell error.Environment
cloudflare/computerat76d9e75(currentmain)examples/container, container backend viacomputerd0.1.0-alpha.1