Skip to content

feat(plugins): say why the sandbox runner is unavailable - #3041

Merged
ascorbic merged 1 commit into
emdash-cms:mainfrom
danielmlr:feat/sandbox-unavailable-reason
Sep 11, 2026
Merged

ascorbic merged 1 commit into
emdash-cms:mainfrom
danielmlr:feat/sandbox-unavailable-reason

Conversation

@danielmlr

Copy link
Copy Markdown
Contributor

What does this PR do?

Names the cause when a configured sandbox runner cannot run plugins. isAvailable() answers only true or false, so a missing worker_loaders binding, a missing PluginBridge export and a workerd binary that does not run all produce the same startup warning and the same SANDBOX_NOT_AVAILABLE refusal.

SandboxRunner gets the optional unavailableReason() the workerd runner already had. The Cloudflare and workerd runners report their cause, and the warning and the four install and update refusals append it after a colon. Runners without the method keep today's text: the noop runner, whose "Sandbox runner is required" already names what is missing, and the Miniflare dev runner, which the factory returns only once Miniflare resolves. The sandbox guide maps each reason to its fix.

Part of #1686 and #1680.

Type of change

  • Bug fix
  • Feature (requires maintainer-approved Discussion)
  • Refactor (no behavior change)
  • Translation
  • Documentation
  • Performance improvement
  • Tests
  • Chore (dependencies, CI, tooling)

Checklist

AI-generated code disclosure

  • This PR includes AI-generated code — model/tool: Claude Opus 5

Screenshots / test output

Not applicable for screenshots. These new tests failed before the change:

 × marketplace install appends the reason the runner gives
 × marketplace update appends the reason the runner gives
 × registry install appends the reason the runner gives
 × registry update appends the reason the runner gives
 × names the reason the runner gives in the startup warning
 × names the Worker Loader binding when it is missing
 × names the PluginBridge export when it is missing
 × names both when both are missing
 × names the binary when it does not run

AssertionError: expected 'Sandbox runner is required for market…' to match
  /: the worker has no worker_loaders bi…/
TypeError: runner.unavailableReason is not a function
AssertionError: expected 'workerd is not running' to contain 'binary'

With the change:

pnpm --filter emdash test                        542 files, 6516 tests passed, 10 skipped
pnpm --filter @emdash-cms/cloudflare test         38 files, 422 tests passed, 2 skipped
pnpm --filter @emdash-cms/sandbox-workerd test    14 files, 92 tests passed

pnpm typecheck, pnpm lint, pnpm format and the docs build are clean. pnpm test:e2e was not run.

isAvailable() answers only true or false, so a missing worker_loaders
binding, a missing PluginBridge export and a workerd binary that does not
run all produced the same startup warning and the same
SANDBOX_NOT_AVAILABLE refusal on install and update.

SandboxRunner gains an optional unavailableReason(). The Cloudflare and
workerd runners report their cause, and the startup warning and the four
refusals append it; runners without the method keep the previous text.
@changeset-bot

changeset-bot Bot commented Sep 10, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: bcb9351

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 17 packages
Name Type
emdash Minor
@emdash-cms/cloudflare Minor
@emdash-cms/sandbox-workerd Patch
@emdash-cms/fixture-perf-site Patch
@emdash-cms/perf-demo-site Patch
@emdash-cms/cache-demo-site Patch
@emdash-cms/do-demo-site Patch
@emdash-cms/do-solo-demo-site Patch
@emdash-cms/admin Minor
@emdash-cms/auth Minor
@emdash-cms/blocks Minor
create-emdash Minor
@emdash-cms/gutenberg-to-portable-text Minor
@emdash-cms/x402 Minor
@emdash-cms/auth-atproto Patch
@emdash-cms/release-service Patch
@emdash-cms/plugin-embeds Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions

Copy link
Copy Markdown
Contributor

PR template validation failed

Please fix the following issues by editing your PR description:

See CONTRIBUTING.md for the full contribution policy.

@pkg-pr-new

pkg-pr-new Bot commented Sep 10, 2026

Copy link
Copy Markdown

Open in StackBlitz

@emdash-cms/admin

npm i https://pkg.pr.new/@emdash-cms/admin@3041

@emdash-cms/auth

npm i https://pkg.pr.new/@emdash-cms/auth@3041

@emdash-cms/auth-atproto

npm i https://pkg.pr.new/@emdash-cms/auth-atproto@3041

@emdash-cms/blocks

npm i https://pkg.pr.new/@emdash-cms/blocks@3041

@emdash-cms/cloudflare

npm i https://pkg.pr.new/@emdash-cms/cloudflare@3041

@emdash-cms/contentful-to-portable-text

npm i https://pkg.pr.new/@emdash-cms/contentful-to-portable-text@3041

emdash

npm i https://pkg.pr.new/emdash@3041

create-emdash

npm i https://pkg.pr.new/create-emdash@3041

@emdash-cms/gutenberg-to-portable-text

npm i https://pkg.pr.new/@emdash-cms/gutenberg-to-portable-text@3041

@emdash-cms/plugin-cli

npm i https://pkg.pr.new/@emdash-cms/plugin-cli@3041

@emdash-cms/plugin-types

npm i https://pkg.pr.new/@emdash-cms/plugin-types@3041

@emdash-cms/registry-client

npm i https://pkg.pr.new/@emdash-cms/registry-client@3041

@emdash-cms/registry-lexicons

npm i https://pkg.pr.new/@emdash-cms/registry-lexicons@3041

@emdash-cms/registry-moderation

npm i https://pkg.pr.new/@emdash-cms/registry-moderation@3041

@emdash-cms/registry-verification

npm i https://pkg.pr.new/@emdash-cms/registry-verification@3041

@emdash-cms/sandbox-workerd

npm i https://pkg.pr.new/@emdash-cms/sandbox-workerd@3041

@emdash-cms/x402

npm i https://pkg.pr.new/@emdash-cms/x402@3041

@emdash-cms/plugin-ai-moderation

npm i https://pkg.pr.new/@emdash-cms/plugin-ai-moderation@3041

@emdash-cms/plugin-atproto

npm i https://pkg.pr.new/@emdash-cms/plugin-atproto@3041

@emdash-cms/plugin-audit-log

npm i https://pkg.pr.new/@emdash-cms/plugin-audit-log@3041

@emdash-cms/plugin-color

npm i https://pkg.pr.new/@emdash-cms/plugin-color@3041

@emdash-cms/plugin-embeds

npm i https://pkg.pr.new/@emdash-cms/plugin-embeds@3041

@emdash-cms/plugin-field-kit

npm i https://pkg.pr.new/@emdash-cms/plugin-field-kit@3041

@emdash-cms/plugin-forms

npm i https://pkg.pr.new/@emdash-cms/plugin-forms@3041

@emdash-cms/plugin-webhook-notifier

npm i https://pkg.pr.new/@emdash-cms/plugin-webhook-notifier@3041

commit: bcb9351

@github-actions

Copy link
Copy Markdown
Contributor

Overlapping PRs

This PR modifies files that are also changed by other open PRs:

This may cause merge conflicts or duplicated work. A maintainer will coordinate.

@danielmlr
danielmlr marked this pull request as ready for review September 10, 2026 20:24

@emdashbot emdashbot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a well-scoped, backwards-compatible improvement. Adding an optional unavailableReason() to SandboxRunner and wiring it into the startup warning and the four SANDBOX_NOT_AVAILABLE refusal paths is the right-shaped fix for the issue described in #1680/#1686: today the same opaque message hides several distinct misconfigurations.

I read the full diff, the changed source files, the test files, the changeset, and the docs update. I also checked the existing MiniflareDevRunner and the three SandboxRunner implementations to confirm the optional method does not break third-party runners or the dev runner.

What I checked:

  • Approach: the change is additive (optional interface method), keeps existing plain messages for runners that don't implement it, and is consistent across Cloudflare (worker_loaders binding / PluginBridge export) and Node.js (workerd binary check).
  • API surface: withUnavailableReason correctly handles a null runner and a runner without unavailableReason; callers use the exact same SandboxRunner | null type they already had.
  • Behavior: EmDashRuntime logs the reason when present and falls back to the prior workerd-specific guidance when absent; handlers append the reason for marketplace install/update and registry install/update.
  • Tests: new tests pin the Cloudflare runner outputs, the workerd binary failure reason, all four refusal messages, and the startup warning. They exercise observable error messages, not implementation details.
  • Docs: the plugin-sandbox troubleshooting section maps each new reason to its fix and matches the implementation.
  • Changeset: follows .changeset/README.md — present tense, names the affected error/warning, proportional detail, no unnecessary headings.

I didn't find any logic bugs, regressions, AGENTS.md convention violations, or missing test coverage. The PR is ready to merge as-is.

@github-actions github-actions Bot added the review/approved Approved; no new commits since label Sep 10, 2026

@ascorbic ascorbic left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@ascorbic
ascorbic merged commit 0ae2f26 into emdash-cms:main Sep 11, 2026
55 of 56 checks passed
@emdashbot emdashbot Bot mentioned this pull request Sep 11, 2026
@danielmlr
danielmlr deleted the feat/sandbox-unavailable-reason branch September 11, 2026 15:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants