Sitelet https://github.com/NodeOps-app/createos-sandbox-sdk/pull/47
Skip to content

fix(examples): unbreak the 21 failing examples in the nightly matrix - #47

Merged
pratikbin merged 5 commits into
mainfrom
fix/ci-example-failures
Sep 7, 2026
Merged

pratikbin merged 5 commits into
mainfrom
fix/ci-example-failures

Conversation

@pratikbin

Copy link
Copy Markdown
Contributor

The nightly example matrix reported success while 21 of its 51 examples
failed — example failures are advisory, so nothing turned the run red.
Run 33487941064
was the starting point; this branch takes it from 21 failures to 4.

Root causes and fixes

# Cause Fix
04 06 12 13 16 17 20 32 33 35 44 45 46 47 53 Every LLM call returned 400 failed to get config for provider deepseek: not found. The gateway's only configured provider is openrouter, and the model secrets named deepseek/deepseek-v4-pro — so bifrost read the first path segment as a provider it does not have. secrets only — OPENAI_MODEL / ANTHROPIC_MODEL / LLM_MODEL now carry the openrouter/ prefix. No code change.
49 50 51 .env.ant is gitignored and never exists in CI, so the loader threw ENOENT before doing anything. Read credentials from the process env first, treat the dotenv as an optional fallback. The org key is read as ANTHROPIC_ORG_API_KEY — a distinct name, because in CI ANTHROPIC_API_KEY is the gateway key and Managed Agents talks to api.anthropic.com directly.
41 JSON.parse(stdout) failed — MuPDF writes warnings to stdout. The extractor writes JSON to a file the host downloads.
09 npm install … 2>&1 merged stderr into stdout, so the throw reported an empty stderr. Underneath: the rootfs ships claude as an asdf shim that re-execs asdf, and the asdf tree lives under /root (mode 700) — invisible to the non-root user --dangerously-skip-permissions requires, giving a bare 127. Install only when absent, open /root for traversal (+x, not +r), and invoke the real binary. Errors now report both streams.
52 resume() returns before the sandbox has an IP; files.download then 503s with sandbox has no ip. Wait for running and an IP.
55 The desktop stack boots after the sandbox, so the first computer.screen call 409s with desktop_unavailable. Retry until it answers, bounded at 120s.
13 On a snapshot timeout the recovery path swallowed both failures and queried a still-paused sandbox, surfacing as an opaque 409 sandbox is paused; resume first. Retry resume until running, then fail with a clear message.
— A secret whose value was 1 made GitHub mask every 1 in every log line (bun install v***.4.0). S3_USE_PATH_STYLE is a plain literal in the workflows now; it was never sensitive.

Both workflows also gained ANCHOR_API_KEY, FIRECRAWL_API_KEY and the
Managed Agents credentials in env:.

Verification

Full matrix on this branch:
33600552945 — 4 failures left, none of them a code defect:

  • 49 50 51 — the Anthropic organization key is invalid. Tested straight
    against api.anthropic.com: 401 {"type":"authentication_error","message":"API key is invalid."}.
    Needs a fresh key, not a code change.
  • 12-radicle — node-start exited 1 with empty stdout and stderr, ~36s
    in; passed in the two preceding runs. Node-boot flake.

Known gap, not addressed here: example 09 is green but returns empty output,
because Claude Code does not recognize openrouter/deepseek/deepseek-v4-pro
and skips the work. Pointing ANTHROPIC_MODEL at a recognized id fixes it.

Nightly cron run 33487941064 was green while 21 of 51 examples failed
(failures are advisory). Fixes the ones that are ours:

- 49/50/51: `.env.ant` is gitignored and never exists in CI, so the
  loader threw ENOENT before doing anything. Read credentials from the
  process env first (under ANTHROPIC_ORG_API_KEY, a distinct name so the
  shared gateway's ANTHROPIC_API_KEY can never be mistaken for the
  organization key), and treat the dotenv as an optional fallback.
- 41: MuPDF writes warnings to stdout, so `JSON.parse(stdout)` failed.
  The extractor now writes JSON to a file the host downloads.
- 09: `npm install ... 2>&1` merged stderr into stdout, so the throw
  reported an empty stderr. Drop the redirect, report both streams.
- 52: `resume()` returns before the sandbox has an IP; `files.download`
  then 503s with "sandbox has no ip". Wait for running + an IP.
- workflows: wire ANCHOR_API_KEY / FIRECRAWL_API_KEY and the Managed
  Agents credentials into the job env, and stop passing
  S3_USE_PATH_STYLE as a secret — its value ("1") made GitHub mask
  every "1" in every log line.
- 09: the devbox rootfs already ships the claude CLI, so `npm install -g`
  died with EEXIST (visible only after the previous commit stopped
  swallowing npm's stderr). Install only when the binary is absent.
- 13: when the pause/resume demo timed out, the recovery path swallowed
  both the resume and the wait failure and queried a still-paused
  sandbox, surfacing as an opaque 409 "sandbox is paused; resume first".
  Retry resume until running, then fail with a clear message.
- 09: the rootfs ships `claude` outside /usr/local/bin, so the previous
  `command -v` guard skipped the install and the non-root task — which
  only sees /usr/local/bin — died with exit 127. Guard on the path.
- 55: the desktop stack boots after the sandbox, so the first
  `computer.screen` call 409s with `desktop_unavailable`. Retry until it
  answers, bounded at 120s.
The claude shim resolves node through `env`, but the rootfs keeps node
under /root (mode 700), so dropping to sandboxuser produced a bare exit
127. Copy node onto /usr/local/bin, and stop merging stderr into stdout
so a future failure reports something.
`claude` on PATH is an asdf shim that re-execs `asdf`, and the asdf tree
lives under /root (mode 700) — so once the example drops to a non-root
user (required by --dangerously-skip-permissions) the shim died with a
bare 127. Open /root for traversal only and link the real binary.
@pratikbin
pratikbin merged commit 6a2b941 into main Sep 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant