diff --git a/code/lib/core-events/src/errors/server-errors.ts b/code/lib/core-events/src/errors/server-errors.ts index 6ca430ae1966..964bbbb64a92 100644 --- a/code/lib/core-events/src/errors/server-errors.ts +++ b/code/lib/core-events/src/errors/server-errors.ts @@ -385,3 +385,28 @@ export class NextjsSWCNotSupportedError extends StorybookError { `; } } + +export class NoMatchingExportError extends StorybookError { + readonly category = Category.CORE_SERVER; + + readonly code = 4; + + constructor(public data: { error: unknown | Error }) { + super(); + } + + template() { + return dedent` + There was an exports mismatch error when trying to build Storybook. + Please check whether the versions of your Storybook packages match whenever possible, as this might be the cause. + + Problematic example: + { "@storybook/react": "7.5.3", "@storybook/react-vite": "7.4.5", "storybook": "7.3.0" } + + Correct example: + { "@storybook/react": "7.5.3", "@storybook/react-vite": "7.5.3", "storybook": "7.5.3" } + + Clearing your lock file and reinstalling your dependencies might help as well, as sometimes the version you see in your package.json might not be the one defined in your lock file, leading to version inconsistency issues. + `; + } +} diff --git a/code/lib/core-server/src/build-dev.ts b/code/lib/core-server/src/build-dev.ts index 1e321a7d2933..2811d93905f9 100644 --- a/code/lib/core-server/src/build-dev.ts +++ b/code/lib/core-server/src/build-dev.ts @@ -27,6 +27,7 @@ import { updateCheck } from './utils/update-check'; import { getServerPort, getServerChannelUrl } from './utils/server-address'; import { getManagerBuilder, getPreviewBuilder } from './utils/get-builders'; import { warnOnIncompatibleAddons } from './utils/warnOnIncompatibleAddons'; +import { buildOrThrow } from './utils/build-or-throw'; export async function buildDevStandalone( options: CLIOptions & LoadOptions & BuilderOptions @@ -134,8 +135,8 @@ export async function buildDevStandalone( features, }; - const { address, networkAddress, managerResult, previewResult } = await storybookDevServer( - fullOptions + const { address, networkAddress, managerResult, previewResult } = await buildOrThrow(async () => + storybookDevServer(fullOptions) ); const previewTotalTime = previewResult?.totalTime; diff --git a/code/lib/core-server/src/build-static.ts b/code/lib/core-server/src/build-static.ts index e6775f519829..cde136c47413 100644 --- a/code/lib/core-server/src/build-static.ts +++ b/code/lib/core-server/src/build-static.ts @@ -35,6 +35,7 @@ import { extractStorybookMetadata } from './utils/metadata'; import { StoryIndexGenerator } from './utils/StoryIndexGenerator'; import { summarizeIndex } from './utils/summarizeIndex'; import { defaultStaticDirs } from './utils/constants'; +import { buildOrThrow } from './utils/build-or-throw'; export type BuildStaticStandaloneOptions = CLIOptions & LoadOptions & @@ -146,7 +147,9 @@ export async function buildStaticStandalone(options: BuildStaticStandaloneOption global.FEATURES = features; - await managerBuilder.build({ startTime: process.hrtime(), options: fullOptions }); + await buildOrThrow(async () => + managerBuilder.build({ startTime: process.hrtime(), options: fullOptions }) + ); if (staticDirs) { effects.push( diff --git a/code/lib/core-server/src/utils/build-or-throw.ts b/code/lib/core-server/src/utils/build-or-throw.ts new file mode 100644 index 000000000000..5c1746a0be2a --- /dev/null +++ b/code/lib/core-server/src/utils/build-or-throw.ts @@ -0,0 +1,20 @@ +import { NoMatchingExportError } from '@storybook/core-events/server-errors'; + +export async function buildOrThrow(callback: () => Promise): Promise { + try { + return await callback(); + } catch (err: any) { + const builderErrors = err.errors as { text: string }[]; + if (builderErrors) { + const inconsistentVersionsError = builderErrors.find((er) => + er.text?.includes('No matching export') + ); + + if (inconsistentVersionsError) { + throw new NoMatchingExportError(err); + } + } + + throw err; + } +}