feat: expose an erroring output's message with useShinyOutputError - #259
Open
schloerke wants to merge 2 commits into
Open
feat: expose an erroring output's message with useShinyOutputError#259schloerke wants to merge 2 commits into
schloerke wants to merge 2 commits into
Conversation
) A `reactive_output` that errored told the client only *that* it errored: `useShinyOutputStatus(id)` returned `"error"` and the message stopped at the registry. Apps being ported to the ui.tsx pattern could not reproduce their own original error UI, which vanilla Shiny paints from the sanitized condition text. The output registry already cached and fanned out the error, so this is a new read-only hook over an existing channel: - `useShinyOutputError(id, options?)` → `{message, call, type} | null`, subscribing to the error channel only and resetting on id/namespace change. - No server-side change in either package: `reactive_output` is an ordinary renderer, so the message arrives already sanitized by shiny itself (`shiny.sanitize.errors` / `sanitize_errors`). Silent errors are now the same shape in both languages. R sends `req()` as an error with an empty message (vanilla Shiny blanks the output element); py-shiny sends a `null` value. `setError` with an empty message is now handled as `setValue(null)`, so one React component sees the same thing from either server and no message is surfaced. Tests: a JS hook suite plus registry coverage of the empty-message mapping, and a Playwright fixture that drives an erroring output end to end (error text, recovery, and a silent `req()`). R has no e2e suite yet (#194). Docs: FEATURES.md leaves, CLAUDE.md, both READMEs, and the shipped shinyreact-build-app skill.
…space-changes # Conflicts: # pkg-js/dist/shinyreact.js # pkg-py/src/shinyreact/www/shinyreact.js # pkg-r/inst/lib/shiny/shinyreact.js
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #257.
The gap
When a
reactive_outputerrored, the client could only learn that it errored —useShinyOutputStatus(id)returned"error"and the message stopped at the output registry. Both stock-app ports in the skills benchmark had to record "error text not reproduced verbatim" as a forced divergence.The fix
The registry already cached the error and fanned it out to subscribers; nothing exposed it. So this is a new read-only hook over an existing channel:
useShinyOutputError(id, options?)→{message, call, type} | nullnullwhenever the output is not in the"error"state.[r]call/typecarry the condition's call and extra classes;[py]both arenull.No server-side change in either package.
reactive_outputis an ordinary Shiny renderer, so the message arrives already sanitized by shiny itself (shiny.sanitize.errors/sanitize_errors) — the client never has to decide what is safe to show.Silent errors, and an R/Python parity fix
R sends
req()as an error with an empty message (vanilla Shiny blanks the output element); py-shiny sends anullvalue for the samereq().setErrorwith an empty message is now handled assetValue(null), so one React component sees the same thing from either server, and a silent error surfaces no message.Tests
pkg-js/src/shiny-react/__tests__/use-shiny-output-error.test.tsx— 5 cases (first delivery, late-mount sync, clearing on a value, silent error, id change).output-registry.test.tspins the empty-message →nullvalue mapping;global.test.tspins the widenedwindow.shinyreactsurface.pkg-py/tests/playwright/apps/output-error/+test_output_error.py— e2e: the server'sValueErrortext reaches the client and clears on recovery, andreq()blanks the value with no error. R has no e2e suite yet (Add an R Playwright e2e suite #194).Green locally: JS 262, Python 146 + pyright clean, R 237, Playwright 12.
Docs
FEATURES.mdleaves (hook behavior, the[r]-only silent-error shape,(e2e)markers),CLAUDE.mdhook table, both READMEs, and the shippedshinyreact-build-appskill (hook table, an error-UI snippet, debugging + modules references), withmake update-skillsandmake update-distrun.