Skip to content

[Blueprints] Surface more activation errors from activatePlugin - #3549

Merged
adamziel merged 4 commits into
trunkfrom
adamziel/activate-plugin-error
Apr 28, 2026
Merged

[Blueprints] Surface more activation errors from activatePlugin#3549
adamziel merged 4 commits into
trunkfrom
adamziel/activate-plugin-error

Conversation

@adamziel

Copy link
Copy Markdown
Collaborator

Summary

When a plugin failed to activate because activate_plugin() returned a WP_Error (unmet PHP requirement, missing plugin file, plugin printing output during validation, etc.), the thrown JS error read "WordPress exited with exit code 0" — useless. The actual WP_Error message was sitting in the activation script's stdout, only emitted as a logger.warn, and any error_log() output during activation went to debug.log where the caller had to know to look.

Route this request's PHP errors to a scratch log file owned by the step (ini_set per-request, no impact on the user's debug.log), then on the failure path include both the WordPress die() text and any logged PHP errors in the rejected promise. Drops the misleading exit-code wording, since by the time we reach that branch php.run() has already returned with exit code 0 — non-zero exits throw upstream with stdout+stderr already.

Adds a regression test for the WP_Error branch, which previously had no coverage.

Test plan

  • CI runs playground-blueprints test suite, including the new "unmet PHP requirement" case
  • Existing activation tests ("noisy plugin", "already active", "throws on uncaught exception") still pass — none of those paths reach the rewritten throw
When a plugin failed to activate because activate_plugin() returned a WP_Error (unmet PHP requirement, missing plugin file, plugin already active and printing output, etc.), the thrown JS error said only "WordPress exited with exit code 0" — useless. The actual WP_Error message was sitting in the activation script's stdout, only logged as a warning, and any error_log() output during activation went to debug.log where the caller had to know to look.

Route this request's PHP errors to a scratch log file owned by the step (ini_set per-request, no impact on the user's debug.log), then on failure include both the WordPress die() text and any logged PHP errors in the rejected promise. Adds a regression test for the WP_Error path, which had no coverage.

Copilot AI 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.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Improves the activatePlugin blueprint step by surfacing meaningful activation failure details (WP_Error output + PHP error logs) instead of a misleading generic exit-code error, and adds a regression test for this failure mode.

Changes:

  • Capture PHP error_log() output during activation into a per-request scratch log and include it in the thrown JS error on failure.
  • Improve the thrown error message to include the WordPress die() text (typically WP_Error message) and any PHP log output.
  • Add a regression test covering activation rejection due to unmet PHP requirements.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

File Description
packages/playground/blueprints/src/lib/steps/activate-plugin.ts Adds scratch logging for activation and surfaces WP output + PHP logs in the thrown error message.
packages/playground/blueprints/src/lib/steps/activate-plugin.spec.ts Adds a test ensuring WP_Error activation messages are surfaced to the caller.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/playground/blueprints/src/lib/steps/activate-plugin.ts
Comment thread packages/playground/blueprints/src/lib/steps/activate-plugin.ts Outdated
Comment thread packages/playground/blueprints/src/lib/steps/activate-plugin.ts
Comment thread packages/playground/blueprints/src/lib/steps/activate-plugin.spec.ts Outdated
- Drain the scratch log immediately after activation so it's cleaned up on success too, not only on the failure path.
- Loosen the WP_Error test regex to assert "WordPress said:" plus any non-empty content, instead of depending on the literal "PHP" appearing in WP's localized error string.
… coverage

Restored the "Response headers: {...}" trailer the previous error message had — it's the only signal when activation fails via a redirect with no body — and added a one-liner pointing readers at the Playground console (browser DevTools) or the CLI output for additional logs, so the message is useful in both environments.

Expanded the spec with assertions on specific failure messages: the WP_Error path keeps its check that the WordPress text mentions PHP, plus three new cases — missing plugin file, response-headers + console-pointer in the message, and PHP error_log() output captured into the scratch log via a plugin that prints unexpected output during sandbox scrape.
The missing-plugin test asserted the snippet's "wasn't able to find" string, but WordPress's validate_plugin returns a WP_Error("Plugin file does not exist.") before the snippet's false-fallback can trigger — assert that message instead. The error_log capture test fixture printed at file scope, which still ends up activating the plugin (per the existing comment in activate-plugin.ts), so the rejection never happened — switched to a register_activation_hook that error_logs then wp_die()s, which fires before active_plugins is written and exercises the real failure-with-log-capture path.
@adamziel adamziel changed the title [Blueprints] Surface real activation errors from activatePlugin Apr 28, 2026
@adamziel
adamziel merged commit fea7a78 into trunk Apr 28, 2026
136 of 140 checks passed
@adamziel
adamziel deleted the adamziel/activate-plugin-error branch April 28, 2026 19:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment