-
-
Notifications
You must be signed in to change notification settings - Fork 10.1k
Core: Add error categorization framework #23653
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
28 commits
Select commit
Hold shift + click to select a range
eee0600
add new errors framework
yannbf ed7e628
add first examples of categorized errors
yannbf ce66635
add telemetry event to core-server
yannbf 0e9d1d9
add motivation
yannbf 94c7cd0
add typings for global
yannbf 40acb07
refactor error telemetry
yannbf 239b3a7
refactor core-event errors
yannbf ede49ce
add local eslint plugin for custom monorepo rules
yannbf 10dd616
add more categories
yannbf 16e3684
update docs
yannbf 535bb89
update lockfile
yannbf d37b713
improve error message
yannbf b731f3f
move local rules eslint plugin to scripts
yannbf 74ab63d
refactor code based on review comments
yannbf 7686bd9
update imports
yannbf d64045c
prepare for new version of telejson
yannbf 3b1c1c4
upgrade telejson
yannbf f21cf3a
add storybook error metadata
yannbf 5531d1f
use @storybook/global in preview runtime
yannbf 21ef39d
remove telemetry property
yannbf 8cc89dc
small documentation changes
yannbf a06f84e
switch to using portals
yannbf 16f9d32
remove telemetry property
yannbf a5e2321
add browser telemetry type
yannbf 041f25c
add uncaught manager error
yannbf d970053
fix types
yannbf 7192433
fix types
yannbf d608010
fix test
yannbf File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
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
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
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
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
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,156 @@ | ||
| # Storybook Errors | ||
|
|
||
| Storybook provides a utility to manage errors thrown from it. Each error is categorized and coded, and there is an ESLint plugin which enforces their usage, instead of throwing generic errors like `throw new Error()`. | ||
|
|
||
| Storybook errors reside in this package and are categorized into: | ||
|
|
||
| 1. **[Preview errors](./preview-errors.ts)** | ||
| - Errors which occur in the preview part of Storybook (where user code executes) | ||
| - e.g. Rendering issues, etc. | ||
| - available in `@storybook/core-events/preview-errors` | ||
| 2. **[Manager errors](./manager-errors.ts)** | ||
| - Errors which occur in the manager part of Storybook (manager UI) | ||
| - e.g. Sidebar, addons, Storybook UI, Storybook router, etc. | ||
| - available in `@storybook/core-events/server-errors` | ||
| 3. **[Server errors](./server-errors.ts)** | ||
| - Errors which occur in node | ||
| - e.g. Storybook init command, dev command, builder errors (Webpack, Vite), etc. | ||
| - available in `@storybook/core-events/server-errors` | ||
|
|
||
| ## How to create errors | ||
|
|
||
| First, **find which file your error should be part of**, based on the criteria above. | ||
| Second use the `StorybookError` class to define custom errors with specific codes and categories for use within the Storybook codebase. Below is a detailed documentation for the error properties: | ||
|
|
||
| ### Class Structure | ||
|
|
||
| ```typescript | ||
| import { StorybookError } from './storybook-error'; | ||
| export class YourCustomError extends StorybookError { | ||
| readonly category: Category; // The category to which the error belongs. Check the source in client-errors.ts or server-errors.ts for reference. | ||
| readonly code: number; // The numeric code for the error. | ||
|
|
||
| template(): string { | ||
| // A function that returns the error message. | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| ### Properties | ||
|
|
||
| | Name | Type | Description | | ||
| | ------------- | --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | | ||
| | category | `Category` | The category to which the error belongs. | | ||
| | code | `number` | The numeric code for the error. | | ||
| | template | `() => string` | Function that returns a properly written error message. | | ||
| | data | `Object` | Optional. Data associated with the error. Used to provide additional information in the error message or to be passed to telemetry. | | ||
| | documentation | `boolean` or `string` | Optional. Should be set to `true` **if the error is documented on the Storybook website**. If defined as string, it should be a custom documentation link. | | ||
|
|
||
| ## Usage Example | ||
|
|
||
| ```typescript | ||
| // Define a custom error with a numeric code and a static error message template. | ||
| export class StorybookIndexGenerationError extends StorybookError { | ||
| category = Category.Generic; | ||
| code = 1; | ||
|
|
||
| template(): string { | ||
| return `Storybook failed when generating an index for your stories. Check the stories field in your main.js`; | ||
| } | ||
| } | ||
|
|
||
| // Define a custom error with a numeric code and a dynamic error message template based on properties from the constructor. | ||
| export class InvalidFileExtensionError extends StorybookError { | ||
| category = Category.Validation; | ||
| code = 2; | ||
| documentation = 'https://some-custom-documentation.com/validation-errors'; | ||
|
|
||
| // extra properties are defined in the constructor via a data property, which is available in any class method | ||
| // always use this data Object notation! | ||
| constructor(public data: { extension: string }) { | ||
| super(); | ||
| } | ||
|
|
||
| template(): string { | ||
| return `Invalid file extension found: ${this.data.extension}.`; | ||
| } | ||
| } | ||
|
|
||
| // import the errors where you need them, i.e. | ||
| import { | ||
| StorybookIndexGenerationError, | ||
| InvalidFileExtensionError, | ||
| } from '@storybook/core-events/server-errors'; | ||
|
|
||
| throw StorybookIndexGenerationError(); | ||
| // "SB_Generic_0001: Storybook failed when generating an index for your stories. Check the stories field in your main.js. | ||
|
|
||
| throw InvalidFileExtensionError({ extension: 'mtsx' }); | ||
| // "SB_Validation_0002: Invalid file extension found: mtsx. More info: https://some-custom-documentation.com/validation-errors" | ||
| ``` | ||
|
|
||
| ## How to write a proper error message | ||
|
|
||
| Writing clear and informative error messages is crucial for effective debugging and troubleshooting. A well-crafted error message can save developers and users valuable time. Consider the following guidelines: | ||
|
|
||
| - **Be clear and specific:** Provide straightforward error messages that precisely describe the issue. | ||
| - **Include relevant context:** Add details about the error's origin and relevant context to aid troubleshooting. | ||
|
yannbf marked this conversation as resolved.
|
||
| - **Provide guidance for resolution:** Offer actionable steps to resolve the error or suggest potential fixes. | ||
| - **Provide documentation links:** Whenever applicable, provide links for users to get guidance or more context to fix their issues. | ||
|
|
||
| <img src="./message-reference.png" width="800px" /> | ||
|
|
||
| ✅ Here are a few recommended examples: | ||
|
|
||
| Long: | ||
|
|
||
| ``` | ||
| Couldn't find story matching id 'component--button-primary' after HMR. | ||
| - Did you just rename a story? | ||
| - Did you remove it from your CSF file? | ||
| - Are you sure a story with the id 'component--button-primary' exists? | ||
| - Please check the values in the stories field of your main.js config and see if they would match your CSF File. | ||
| - Also check the browser console and terminal for potential error messages. | ||
| ``` | ||
|
|
||
| Medium: | ||
|
|
||
| ``` | ||
| Addon-docs no longer uses configureJsx or mdxBabelOptions in 7.0. | ||
|
|
||
| To update your configuration, please see migration instructions here: | ||
|
|
||
| https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#dropped-addon-docs-manual-babel-configuration | ||
| ``` | ||
|
|
||
| Short: | ||
|
|
||
| ``` | ||
| Failed to start Storybook. | ||
|
|
||
| Do you have an error in your \`preview.js\`? Check your Storybook's browser console for errors. | ||
| ``` | ||
|
|
||
| ❌ Here are a few unrecommended examples: | ||
|
yannbf marked this conversation as resolved.
|
||
|
|
||
| ``` | ||
| outputDir is required | ||
| ``` | ||
|
|
||
| ``` | ||
| Cannot render story | ||
| ``` | ||
|
|
||
| ``` | ||
| no builder configured! | ||
| ``` | ||
|
|
||
| ## What's the motivation for this errors framework? | ||
|
|
||
| Centralizing and categorizing errors offers several advantages: | ||
|
|
||
| Better understanding of what is actually failing: By defining categories, error origins become more evident, easing the debugging process for developers and providing users with actionable insights. | ||
|
|
||
| Improved Telemetry: Aggregating and filtering errors allows better assessment of their impact, which helps in prioritization and tackling the issues. | ||
|
|
||
| Improved Documentation: Categorized errors lead to the creation of a helpful errors page on the Storybook website, benefiting users with better guidance and improving overall accessibility and user experience. | ||
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| import { StorybookError } from './storybook-error'; | ||
|
|
||
| /** | ||
| * If you can't find a suitable category for your error, create one | ||
| * based on the package name/file path of which the error is thrown. | ||
| * For instance: | ||
| * If it's from @storybook/client-logger, then MANAGER_CLIENT-LOGGER | ||
| * | ||
| * Categories are prefixed by a logical grouping, e.g. MANAGER_ | ||
| * to prevent manager and preview errors from having the same category and error code. | ||
| */ | ||
| export enum Category { | ||
| MANAGER_UNCAUGHT = 'MANAGER_UNCAUGHT', | ||
| MANAGER_UI = 'MANAGER_UI', | ||
| MANAGER_API = 'MANAGER_API', | ||
| MANAGER_CLIENT_LOGGER = 'MANAGER_CLIENT-LOGGER', | ||
| MANAGER_CHANNELS = 'MANAGER_CHANNELS', | ||
| MANAGER_CORE_EVENTS = 'MANAGER_CORE-EVENTS', | ||
| MANAGER_ROUTER = 'MANAGER_ROUTER', | ||
| MANAGER_THEMING = 'MANAGER_THEMING', | ||
| } | ||
|
|
||
| export class ProviderDoesNotExtendBaseProviderError extends StorybookError { | ||
| readonly category = Category.MANAGER_UI; | ||
|
|
||
| readonly code = 1; | ||
|
|
||
| template() { | ||
| return `The Provider passed into Storybook's UI is not extended from the base Provider. Please check your Provider implementation.`; | ||
| } | ||
| } | ||
|
|
||
| export class UncaughtManagerError extends StorybookError { | ||
| readonly category = Category.MANAGER_UNCAUGHT; | ||
|
|
||
| readonly code = 1; | ||
|
|
||
| constructor(public error: Error) { | ||
| super(error.message); | ||
| this.stack = error.stack; | ||
| } | ||
|
|
||
| template() { | ||
| return this.message; | ||
| } | ||
| } |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Oops, something went wrong.
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.
Uh oh!
There was an error while loading. Please reload this page.