Skip to content

Friendlier build-time errors: WorkflowBuildError + builders sites - #1840

Closed
pranaygp wants to merge 1 commit into
pranaygp/friendlier-errors-phase-7-observabilityfrom
pranaygp/friendlier-errors-phase-8-build-time
Closed

Friendlier build-time errors: WorkflowBuildError + builders sites#1840
pranaygp wants to merge 1 commit into
pranaygp/friendlier-errors-phase-7-observabilityfrom
pranaygp/friendlier-errors-phase-8-build-time

Conversation

@pranaygp

@pranaygppranaygp commented Apr 23, 2026

Copy link
Copy Markdown
Contributor

Summary

Phase 8 (final) of the friendlier-errors stack — extends the error-quality work from runtime into build-time.

  • Adds WorkflowBuildError in @workflow/errors with an optional hint field (appended after a blank line) and a .is() discriminator.
  • Applies it at user-facing sites in @workflow/builders/base-builder.ts:
    • Failed esbuild phases → hint at the likely fix for the phase
    • Unresolved built-in steps → hint at pnpm install workflow
    • Empty esbuild output → hint that workflow files need "use workflow" / "use step" directives
  • Internal runtime invariants remain plain Error.

Scope note: deliberately kept to @workflow/builders (ESM). Extending WorkflowBuildError into @workflow/next (CJS) needs a dynamic-import bridge similar to the existing eval('import("@workflow/builders")') pattern — can follow up in a separate PR.

Manual test plan

All tests here exercise the build pipeline, not the runtime. Use workbench/nextjs-turbopack and run pnpm build (not pnpm dev).

  • Syntax error in a workflow file → failed esbuild phase:

    // workbench/nextjs-turbopack/app/_workflows/broken.ts'use workflow';exportasyncfunctionbroken(thisisnotvalidts

    Run pnpm build. Expect in build output:

    • WorkflowBuildError with title mentioning the phase (e.g. "Build failed during workflows bundle").
    • A blank line, then hint: Review the esbuild errors above — they come from the workflows bundle. Fix the offending source files and re-run the build.
    • The original esbuild error messages printed before the WorkflowBuildError, not suppressed.
  • Unresolved built-in steps — temporarily rename node_modules/workflow to node_modules/workflow-bak:

    mv node_modules/workflow node_modules/workflow-bak
    cd workbench/nextjs-turbopack && pnpm build
    mv ../../node_modules/workflow-bak ../../node_modules/workflow # restore

    Expect:

    • WorkflowBuildError: "Failed to resolve built-in steps sources."
    • hint: run \pnpm install workflow` to resolve this issue.`
    • cause: preserves the underlying resolution error.
  • Empty workflow directory — move all your workflow files aside (or create a fresh workspace with none):

    mkdir /tmp/wf-empty &&cd /tmp/wf-empty
    # set up minimal package + workflow config with an empty workflows/ dir
    pnpm workflow build

    Or: delete all "use workflow" / "use step" directives from your files. Expect:

    • WorkflowBuildError: "No output files generated from esbuild"
    • hint mentions "use workflow" / "use step" directives.
  • .is() discriminator — in a scratch script:

    import{WorkflowBuildError}from'@workflow/errors';conste=newWorkflowBuildError('x',{hint: 'y'});console.log(WorkflowBuildError.is(e));// trueconsole.log(WorkflowBuildError.is(newError('x')));// false
  • Hint renders below a blank line — verify the hint output appears after a blank line, not jammed onto the title line (visual formatting check).

  • Runtime paths unaffected — run a normal workflow at runtime (pnpm dev and trigger a workflow). Confirm no WorkflowBuildError shows up at runtime; this class should only appear in build output.

Unit tests

  • pnpm --filter @workflow/errors test — 19 total (4 new WorkflowBuildError tests)
  • pnpm --filter @workflow/builders typecheck + test (129 pass)

📚 Friendlier errors stack

Multi-PR initiative inspired by @Schniz's stalled #706:

#PRPhaseSummary
1#1831Phase 1 + 2Ansi rendering primitives + context-violation errors
2#1832Phase 3Structured logger metadata; folds in #1812
3#1836Phase 4SerializationError at serialization / stream / encryption boundaries
4#1837Phase 5Presentation-only user vs SDK attribution (describeError)
5#1838Phase 6Consistency pass on remaining bare throw new Error(...) sites
6#1839Phase 7 foundationData-driven describeRunError + public subpath
7→ this PR (#1840)Phase 8WorkflowBuildError + applications in @workflow/builders
8#1849FollowupsDrop functionName leak, simplify docs framing, redirect stack to user code

Each PR is stacked on the previous one; merge in order.

🤖 Generated with Claude Code

@vercel

vercelBot commented Apr 23, 2026

Copy link
Copy Markdown
Contributor

CopilotAI review requested due to automatic review settings April 23, 2026 16:54
@github-actions

github-actionsBot commented Apr 23, 2026

Copy link
Copy Markdown
Contributor

🧪 E2E Test Results

Some tests failed

Summary

PassedFailedSkippedTotal
❌ 💻 Local Development10522861140
✅ 📦 Local Production10540861140
✅ 🐘 Local Postgres10540861140
✅ 🪟 Windows950095
✅ 📋 Other267018285
Total352222763800

❌ Failed Tests

💻 Local Development (2 failed)

vite-stable (2 failed):

  • error handling error propagation step errors basic step error preserves message and stack trace
  • error handling error propagation step errors cross-file step error preserves message and function names in stack

Details by Category

❌ 💻 Local Development
AppPassedFailedSkipped
✅ astro-stable8906
✅ express-stable8906
✅ fastify-stable8906
✅ hono-stable8906
✅ nextjs-turbopack-canary76019
✅ nextjs-turbopack-stable9500
✅ nextjs-webpack-canary76019
✅ nextjs-webpack-stable9500
✅ nitro-stable8906
✅ nuxt-stable8906
✅ sveltekit-stable8906
❌ vite-stable8726
✅ 📦 Local Production
AppPassedFailedSkipped
✅ astro-stable8906
✅ express-stable8906
✅ fastify-stable8906
✅ hono-stable8906
✅ nextjs-turbopack-canary76019
✅ nextjs-turbopack-stable9500
✅ nextjs-webpack-canary76019
✅ nextjs-webpack-stable9500
✅ nitro-stable8906
✅ nuxt-stable8906
✅ sveltekit-stable8906
✅ vite-stable8906
✅ 🐘 Local Postgres
AppPassedFailedSkipped
✅ astro-stable8906
✅ express-stable8906
✅ fastify-stable8906
✅ hono-stable8906
✅ nextjs-turbopack-canary76019
✅ nextjs-turbopack-stable9500
✅ nextjs-webpack-canary76019
✅ nextjs-webpack-stable9500
✅ nitro-stable8906
✅ nuxt-stable8906
✅ sveltekit-stable8906
✅ vite-stable8906
✅ 🪟 Windows
AppPassedFailedSkipped
✅ nextjs-turbopack9500
✅ 📋 Other
AppPassedFailedSkipped
✅ e2e-local-dev-nest-stable8906
✅ e2e-local-postgres-nest-stable8906
✅ e2e-local-prod-nest-stable8906

📋 View full workflow run


Some E2E test jobs failed:

  • Vercel Prod: failure
  • Local Dev: failure
  • Local Prod: success
  • Local Postgres: success
  • Windows: success

Check the workflow run for details.

@changeset-bot

changeset-botBot commented Apr 23, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: efaba3a

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

This PR includes changesets to release 21 packages
NameType
@workflow/errorsPatch
@workflow/buildersPatch
@workflow/cliPatch
@workflow/corePatch
@workflow/webPatch
workflowPatch
@workflow/world-localPatch
@workflow/world-postgresPatch
@workflow/world-vercelPatch
@workflow/astroPatch
@workflow/nestPatch
@workflow/nextPatch
@workflow/nitroPatch
@workflow/rollupPatch
@workflow/sveltekitPatch
@workflow/vitePatch
@workflow/vitestPatch
@workflow/world-testingPatch
@workflow/web-sharedPatch
@workflow/aiPatch
@workflow/nuxtPatch

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

CopilotAI 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

This PR extends the “friendlier errors” initiative into build-time by introducing a dedicated WorkflowBuildError (with an optional hint) in @workflow/errors and switching key @workflow/builders failure sites to throw it for more actionable build output.

Changes:

  • Add WorkflowBuildError (with hint and .is() discriminator) to @workflow/errors.
  • Update @workflow/builders to throw WorkflowBuildError for esbuild failures, unresolved built-in steps, and empty esbuild output, including user-action hints.
  • Add tests for WorkflowBuildError and publish a changeset for the patch releases.

Reviewed changes

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

FileDescription
packages/errors/src/index.tsAdds WorkflowBuildError class and documentation.
packages/errors/src/build-error.test.tsAdds vitest coverage for WorkflowBuildError behavior.
packages/builders/src/base-builder.tsReplaces generic Error throws with WorkflowBuildError + hints at key build failure sites.
.changeset/friendlier-build-errors.mdDeclares patch releases for @workflow/errors and @workflow/builders.

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

throw new WorkflowBuildError(
`${chalk.red('Failed to resolve built-in steps sources.')}\n\nCaused by: ${chalk.red(String(err))}`,
{
hint: `${chalk.yellow.bold('hint:')} run \`${chalk.cyan.italic('npm install workflow')}\` to resolve this issue.`,

CopilotAIApr 23, 2026

Copy link

Choose a reason for hiding this comment

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

options.hint is stored on the error (and appended to the message). Including a formatted hint: label + Chalk styling inside the hint field makes the hint harder to re-render in other contexts (e.g. structured UI/JSON) and can lead to double “hint:” prefixes. Consider keeping hint as plain text (no label/styling) and applying formatting at the presentation layer (or using @workflow/errors Ansi helpers if appropriate).

Suggested change
hint: `${chalk.yellow.bold('hint:')}run \`${chalk.cyan.italic('npm install workflow')}\` to resolve this issue.`,
hint: 'run `npm install workflow` to resolve this issue.',

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Fixed in efaba3ahint is now stored as plain text ('run \pnpm install workflow` to resolve this issue.') without the hint:label or chalk styling. Per the updated JSDoc onWorkflowBuildError`, the rendering layer is responsible for styling + any "hint:" label. I also stripped the chalk wrappers from the message string in the same throw so it renders cleanly in non-TTY contexts (CI logs, structured serialization).

Comment threadpackages/errors/src/index.ts Outdated
* by the workflow engine) — `WorkflowBuildError` fires during `pnpm build`,
* `next build`, or equivalent, before any workflow has started executing.
*
* Prefer attaching a short, actionable `hint` (e.g. `run \`npm install workflow\``)

CopilotAIApr 23, 2026

Copy link

Choose a reason for hiding this comment

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

The JSDoc example for hint uses npm install workflow, but other new/updated text in this PR uses pnpm install workflow. Please align this example with the recommended guidance (or switch to a package-manager-agnostic example) so docs and error hints don’t conflict.

Suggested change
*Preferattachingashort,actionable`hint`(e.g.`run \`npm install workflow\``)
*Preferattachingashort,actionable`hint`(e.g.`run \`pnpm install workflow\``)

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Fixed in efaba3a — JSDoc example now uses pnpm install workflow, matching the test and the actual call site.

Comment on lines +14 to +20
hint: 'run `pnpm install workflow` and try again',
});
expect(err.hint).toBe('run `pnpm install workflow` and try again');
expect(err.message).toMatchInlineSnapshot(`
"Build failed during steps

run \`pnpm install workflow\` and try again"

CopilotAIApr 23, 2026

Copy link

Choose a reason for hiding this comment

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

This test uses pnpm install workflow in the sample hint string, while some other new hints/docs in this PR use npm install workflow. If the intent is to be package-manager-agnostic (or to standardize on one), consider updating the test string accordingly so it doesn’t implicitly encode the chosen guidance.

Suggested change
hint: 'run `pnpm install workflow` and try again',
});
expect(err.hint).toBe('run `pnpm install workflow` and try again');
expect(err.message).toMatchInlineSnapshot(`
"Build failed during steps
run \`pnpm install workflow\` andtryagain"
hint: 'run `npm install workflow` and try again',
});
expect(err.hint).toBe('run `npm install workflow` and try again');
expect(err.message).toMatchInlineSnapshot(`
"Build failed during steps
run \`npm install workflow\` andtryagain"

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Fixed in efaba3a — all three sites (the hint in base-builder.ts, this test, and the WorkflowBuildError JSDoc example in packages/errors/src/index.ts) now use pnpm install workflow.

throw new WorkflowBuildError(
`${chalk.red('Failed to resolve built-in steps sources.')}\n\nCaused by: ${chalk.red(String(err))}`,
{
hint: `${chalk.yellow.bold('hint:')} run \`${chalk.cyan.italic('npm install workflow')}\` to resolve this issue.`,

CopilotAIApr 23, 2026

Copy link

Choose a reason for hiding this comment

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

The hint text here hard-codes npm install workflow, but elsewhere in this PR (e.g. WorkflowBuildError docs/tests) the guidance mentions pnpm install workflow. Please standardize the suggested command across the repo (or make it package-manager-agnostic, e.g. “install the workflow package”) to avoid confusing users.

Suggested change
hint: `${chalk.yellow.bold('hint:')}run \`${chalk.cyan.italic('npm install workflow')}\` to resolve this issue.`,
hint: `${chalk.yellow.bold('hint:')}install the \`${chalk.cyan.italic('workflow')}\` package to resolve this issue.`,

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Fixed in efaba3a — the hint now reads run \pnpm install workflow` to resolve this issue.` (standardized on pnpm across the hint string, the test, and the JSDoc example).

Add `WorkflowBuildError` class in `@workflow/errors` with optional `hint`
for an actionable next step, and apply it in `@workflow/builders` at
user-facing sites: failed esbuild phases, unresolved built-in steps, and
empty esbuild output now throw `WorkflowBuildError` with a hint pointing
at the likely fix. Runtime invariants remain plain `Error`.
@pranaygp

Copy link
Copy Markdown
ContributorAuthor

Superseded by #1849 — consolidated friendlier-errors PR with all 8 phases + follow-up fixes (ANSI leak, non-retry semantics, shared captureStackTrace helper).

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@pranaygp
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Friendlier build-time errors: WorkflowBuildError + builders sites by pranaygp · Pull Request #1840 · vercel/workflow · GitHub
Skip to content

Friendlier build-time errors: WorkflowBuildError + builders sites - #1840

Closed
pranaygp wants to merge 1 commit into
pranaygp/friendlier-errors-phase-7-observabilityfrom
pranaygp/friendlier-errors-phase-8-build-time
Closed

Friendlier build-time errors: WorkflowBuildError + builders sites#1840
pranaygp wants to merge 1 commit into
pranaygp/friendlier-errors-phase-7-observabilityfrom
pranaygp/friendlier-errors-phase-8-build-time

Conversation

@pranaygp

@pranaygppranaygp commented Apr 23, 2026

Copy link
Copy Markdown
Contributor

Summary

Phase 8 (final) of the friendlier-errors stack — extends the error-quality work from runtime into build-time.

  • Adds WorkflowBuildError in @workflow/errors with an optional hint field (appended after a blank line) and a .is() discriminator.
  • Applies it at user-facing sites in @workflow/builders/base-builder.ts:
    • Failed esbuild phases → hint at the likely fix for the phase
    • Unresolved built-in steps → hint at pnpm install workflow
    • Empty esbuild output → hint that workflow files need "use workflow" / "use step" directives
  • Internal runtime invariants remain plain Error.

Scope note: deliberately kept to @workflow/builders (ESM). Extending WorkflowBuildError into @workflow/next (CJS) needs a dynamic-import bridge similar to the existing eval('import("@workflow/builders")') pattern — can follow up in a separate PR.

Manual test plan

All tests here exercise the build pipeline, not the runtime. Use workbench/nextjs-turbopack and run pnpm build (not pnpm dev).

  • Syntax error in a workflow file → failed esbuild phase:

    // workbench/nextjs-turbopack/app/_workflows/broken.ts'use workflow';exportasyncfunctionbroken(thisisnotvalidts

    Run pnpm build. Expect in build output:

    • WorkflowBuildError with title mentioning the phase (e.g. "Build failed during workflows bundle").
    • A blank line, then hint: Review the esbuild errors above — they come from the workflows bundle. Fix the offending source files and re-run the build.
    • The original esbuild error messages printed before the WorkflowBuildError, not suppressed.
  • Unresolved built-in steps — temporarily rename node_modules/workflow to node_modules/workflow-bak:

    mv node_modules/workflow node_modules/workflow-bak
    cd workbench/nextjs-turbopack && pnpm build
    mv ../../node_modules/workflow-bak ../../node_modules/workflow # restore

    Expect:

    • WorkflowBuildError: "Failed to resolve built-in steps sources."
    • hint: run \pnpm install workflow` to resolve this issue.`
    • cause: preserves the underlying resolution error.
  • Empty workflow directory — move all your workflow files aside (or create a fresh workspace with none):

    mkdir /tmp/wf-empty &&cd /tmp/wf-empty
    # set up minimal package + workflow config with an empty workflows/ dir
    pnpm workflow build

    Or: delete all "use workflow" / "use step" directives from your files. Expect:

    • WorkflowBuildError: "No output files generated from esbuild"
    • hint mentions "use workflow" / "use step" directives.
  • .is() discriminator — in a scratch script:

    import{WorkflowBuildError}from'@workflow/errors';conste=newWorkflowBuildError('x',{hint: 'y'});console.log(WorkflowBuildError.is(e));// trueconsole.log(WorkflowBuildError.is(newError('x')));// false
  • Hint renders below a blank line — verify the hint output appears after a blank line, not jammed onto the title line (visual formatting check).

  • Runtime paths unaffected — run a normal workflow at runtime (pnpm dev and trigger a workflow). Confirm no WorkflowBuildError shows up at runtime; this class should only appear in build output.

Unit tests

  • pnpm --filter @workflow/errors test — 19 total (4 new WorkflowBuildError tests)
  • pnpm --filter @workflow/builders typecheck + test (129 pass)

📚 Friendlier errors stack

Multi-PR initiative inspired by @Schniz's stalled #706:

#PRPhaseSummary
1#1831Phase 1 + 2Ansi rendering primitives + context-violation errors
2#1832Phase 3Structured logger metadata; folds in #1812
3#1836Phase 4SerializationError at serialization / stream / encryption boundaries
4#1837Phase 5Presentation-only user vs SDK attribution (describeError)
5#1838Phase 6Consistency pass on remaining bare throw new Error(...) sites
6#1839Phase 7 foundationData-driven describeRunError + public subpath
7→ this PR (#1840)Phase 8WorkflowBuildError + applications in @workflow/builders
8#1849FollowupsDrop functionName leak, simplify docs framing, redirect stack to user code

Each PR is stacked on the previous one; merge in order.

🤖 Generated with Claude Code

@vercel

vercelBot commented Apr 23, 2026

Copy link
Copy Markdown
Contributor

CopilotAI review requested due to automatic review settings April 23, 2026 16:54
@github-actions

github-actionsBot commented Apr 23, 2026

Copy link
Copy Markdown
Contributor

🧪 E2E Test Results

Some tests failed

Summary

PassedFailedSkippedTotal
❌ 💻 Local Development10522861140
✅ 📦 Local Production10540861140
✅ 🐘 Local Postgres10540861140
✅ 🪟 Windows950095
✅ 📋 Other267018285
Total352222763800

❌ Failed Tests

💻 Local Development (2 failed)

vite-stable (2 failed):

  • error handling error propagation step errors basic step error preserves message and stack trace
  • error handling error propagation step errors cross-file step error preserves message and function names in stack

Details by Category

❌ 💻 Local Development
AppPassedFailedSkipped
✅ astro-stable8906
✅ express-stable8906
✅ fastify-stable8906
✅ hono-stable8906
✅ nextjs-turbopack-canary76019
✅ nextjs-turbopack-stable9500
✅ nextjs-webpack-canary76019
✅ nextjs-webpack-stable9500
✅ nitro-stable8906
✅ nuxt-stable8906
✅ sveltekit-stable8906
❌ vite-stable8726
✅ 📦 Local Production
AppPassedFailedSkipped
✅ astro-stable8906
✅ express-stable8906
✅ fastify-stable8906
✅ hono-stable8906
✅ nextjs-turbopack-canary76019
✅ nextjs-turbopack-stable9500
✅ nextjs-webpack-canary76019
✅ nextjs-webpack-stable9500
✅ nitro-stable8906
✅ nuxt-stable8906
✅ sveltekit-stable8906
✅ vite-stable8906
✅ 🐘 Local Postgres
AppPassedFailedSkipped
✅ astro-stable8906
✅ express-stable8906
✅ fastify-stable8906
✅ hono-stable8906
✅ nextjs-turbopack-canary76019
✅ nextjs-turbopack-stable9500
✅ nextjs-webpack-canary76019
✅ nextjs-webpack-stable9500
✅ nitro-stable8906
✅ nuxt-stable8906
✅ sveltekit-stable8906
✅ vite-stable8906
✅ 🪟 Windows
AppPassedFailedSkipped
✅ nextjs-turbopack9500
✅ 📋 Other
AppPassedFailedSkipped
✅ e2e-local-dev-nest-stable8906
✅ e2e-local-postgres-nest-stable8906
✅ e2e-local-prod-nest-stable8906

📋 View full workflow run


Some E2E test jobs failed:

  • Vercel Prod: failure
  • Local Dev: failure
  • Local Prod: success
  • Local Postgres: success
  • Windows: success

Check the workflow run for details.

@changeset-bot

changeset-botBot commented Apr 23, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: efaba3a

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

This PR includes changesets to release 21 packages
NameType
@workflow/errorsPatch
@workflow/buildersPatch
@workflow/cliPatch
@workflow/corePatch
@workflow/webPatch
workflowPatch
@workflow/world-localPatch
@workflow/world-postgresPatch
@workflow/world-vercelPatch
@workflow/astroPatch
@workflow/nestPatch
@workflow/nextPatch
@workflow/nitroPatch
@workflow/rollupPatch
@workflow/sveltekitPatch
@workflow/vitePatch
@workflow/vitestPatch
@workflow/world-testingPatch
@workflow/web-sharedPatch
@workflow/aiPatch
@workflow/nuxtPatch

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

CopilotAI 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

This PR extends the “friendlier errors” initiative into build-time by introducing a dedicated WorkflowBuildError (with an optional hint) in @workflow/errors and switching key @workflow/builders failure sites to throw it for more actionable build output.

Changes:

  • Add WorkflowBuildError (with hint and .is() discriminator) to @workflow/errors.
  • Update @workflow/builders to throw WorkflowBuildError for esbuild failures, unresolved built-in steps, and empty esbuild output, including user-action hints.
  • Add tests for WorkflowBuildError and publish a changeset for the patch releases.

Reviewed changes

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

FileDescription
packages/errors/src/index.tsAdds WorkflowBuildError class and documentation.
packages/errors/src/build-error.test.tsAdds vitest coverage for WorkflowBuildError behavior.
packages/builders/src/base-builder.tsReplaces generic Error throws with WorkflowBuildError + hints at key build failure sites.
.changeset/friendlier-build-errors.mdDeclares patch releases for @workflow/errors and @workflow/builders.

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

throw new WorkflowBuildError(
`${chalk.red('Failed to resolve built-in steps sources.')}\n\nCaused by: ${chalk.red(String(err))}`,
{
hint: `${chalk.yellow.bold('hint:')} run \`${chalk.cyan.italic('npm install workflow')}\` to resolve this issue.`,

CopilotAIApr 23, 2026

Copy link

Choose a reason for hiding this comment

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

options.hint is stored on the error (and appended to the message). Including a formatted hint: label + Chalk styling inside the hint field makes the hint harder to re-render in other contexts (e.g. structured UI/JSON) and can lead to double “hint:” prefixes. Consider keeping hint as plain text (no label/styling) and applying formatting at the presentation layer (or using @workflow/errors Ansi helpers if appropriate).

Suggested change
hint: `${chalk.yellow.bold('hint:')}run \`${chalk.cyan.italic('npm install workflow')}\` to resolve this issue.`,
hint: 'run `npm install workflow` to resolve this issue.',

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Fixed in efaba3ahint is now stored as plain text ('run \pnpm install workflow` to resolve this issue.') without the hint:label or chalk styling. Per the updated JSDoc onWorkflowBuildError`, the rendering layer is responsible for styling + any "hint:" label. I also stripped the chalk wrappers from the message string in the same throw so it renders cleanly in non-TTY contexts (CI logs, structured serialization).

Comment threadpackages/errors/src/index.ts Outdated
* by the workflow engine) — `WorkflowBuildError` fires during `pnpm build`,
* `next build`, or equivalent, before any workflow has started executing.
*
* Prefer attaching a short, actionable `hint` (e.g. `run \`npm install workflow\``)

CopilotAIApr 23, 2026

Copy link

Choose a reason for hiding this comment

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

The JSDoc example for hint uses npm install workflow, but other new/updated text in this PR uses pnpm install workflow. Please align this example with the recommended guidance (or switch to a package-manager-agnostic example) so docs and error hints don’t conflict.

Suggested change
*Preferattachingashort,actionable`hint`(e.g.`run \`npm install workflow\``)
*Preferattachingashort,actionable`hint`(e.g.`run \`pnpm install workflow\``)

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Fixed in efaba3a — JSDoc example now uses pnpm install workflow, matching the test and the actual call site.

Comment on lines +14 to +20
hint: 'run `pnpm install workflow` and try again',
});
expect(err.hint).toBe('run `pnpm install workflow` and try again');
expect(err.message).toMatchInlineSnapshot(`
"Build failed during steps

run \`pnpm install workflow\` and try again"

CopilotAIApr 23, 2026

Copy link

Choose a reason for hiding this comment

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

This test uses pnpm install workflow in the sample hint string, while some other new hints/docs in this PR use npm install workflow. If the intent is to be package-manager-agnostic (or to standardize on one), consider updating the test string accordingly so it doesn’t implicitly encode the chosen guidance.

Suggested change
hint: 'run `pnpm install workflow` and try again',
});
expect(err.hint).toBe('run `pnpm install workflow` and try again');
expect(err.message).toMatchInlineSnapshot(`
"Build failed during steps
run \`pnpm install workflow\` andtryagain"
hint: 'run `npm install workflow` and try again',
});
expect(err.hint).toBe('run `npm install workflow` and try again');
expect(err.message).toMatchInlineSnapshot(`
"Build failed during steps
run \`npm install workflow\` andtryagain"

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Fixed in efaba3a — all three sites (the hint in base-builder.ts, this test, and the WorkflowBuildError JSDoc example in packages/errors/src/index.ts) now use pnpm install workflow.

throw new WorkflowBuildError(
`${chalk.red('Failed to resolve built-in steps sources.')}\n\nCaused by: ${chalk.red(String(err))}`,
{
hint: `${chalk.yellow.bold('hint:')} run \`${chalk.cyan.italic('npm install workflow')}\` to resolve this issue.`,

CopilotAIApr 23, 2026

Copy link

Choose a reason for hiding this comment

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

The hint text here hard-codes npm install workflow, but elsewhere in this PR (e.g. WorkflowBuildError docs/tests) the guidance mentions pnpm install workflow. Please standardize the suggested command across the repo (or make it package-manager-agnostic, e.g. “install the workflow package”) to avoid confusing users.

Suggested change
hint: `${chalk.yellow.bold('hint:')}run \`${chalk.cyan.italic('npm install workflow')}\` to resolve this issue.`,
hint: `${chalk.yellow.bold('hint:')}install the \`${chalk.cyan.italic('workflow')}\` package to resolve this issue.`,

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Fixed in efaba3a — the hint now reads run \pnpm install workflow` to resolve this issue.` (standardized on pnpm across the hint string, the test, and the JSDoc example).

Add `WorkflowBuildError` class in `@workflow/errors` with optional `hint`
for an actionable next step, and apply it in `@workflow/builders` at
user-facing sites: failed esbuild phases, unresolved built-in steps, and
empty esbuild output now throw `WorkflowBuildError` with a hint pointing
at the likely fix. Runtime invariants remain plain `Error`.
@pranaygp

Copy link
Copy Markdown
ContributorAuthor

Superseded by #1849 — consolidated friendlier-errors PR with all 8 phases + follow-up fixes (ANSI leak, non-retry semantics, shared captureStackTrace helper).

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@pranaygp
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Friendlier build-time errors: WorkflowBuildError + builders sites by pranaygp · Pull Request #1840 · vercel/workflow · GitHub
Skip to content

Friendlier build-time errors: WorkflowBuildError + builders sites - #1840

Closed
pranaygp wants to merge 1 commit into
pranaygp/friendlier-errors-phase-7-observabilityfrom
pranaygp/friendlier-errors-phase-8-build-time
Closed

Friendlier build-time errors: WorkflowBuildError + builders sites#1840
pranaygp wants to merge 1 commit into
pranaygp/friendlier-errors-phase-7-observabilityfrom
pranaygp/friendlier-errors-phase-8-build-time

Conversation

@pranaygp

@pranaygppranaygp commented Apr 23, 2026

Copy link
Copy Markdown
Contributor

Summary

Phase 8 (final) of the friendlier-errors stack — extends the error-quality work from runtime into build-time.

  • Adds WorkflowBuildError in @workflow/errors with an optional hint field (appended after a blank line) and a .is() discriminator.
  • Applies it at user-facing sites in @workflow/builders/base-builder.ts:
    • Failed esbuild phases → hint at the likely fix for the phase
    • Unresolved built-in steps → hint at pnpm install workflow
    • Empty esbuild output → hint that workflow files need "use workflow" / "use step" directives
  • Internal runtime invariants remain plain Error.

Scope note: deliberately kept to @workflow/builders (ESM). Extending WorkflowBuildError into @workflow/next (CJS) needs a dynamic-import bridge similar to the existing eval('import("@workflow/builders")') pattern — can follow up in a separate PR.

Manual test plan

All tests here exercise the build pipeline, not the runtime. Use workbench/nextjs-turbopack and run pnpm build (not pnpm dev).

  • Syntax error in a workflow file → failed esbuild phase:

    // workbench/nextjs-turbopack/app/_workflows/broken.ts'use workflow';exportasyncfunctionbroken(thisisnotvalidts

    Run pnpm build. Expect in build output:

    • WorkflowBuildError with title mentioning the phase (e.g. "Build failed during workflows bundle").
    • A blank line, then hint: Review the esbuild errors above — they come from the workflows bundle. Fix the offending source files and re-run the build.
    • The original esbuild error messages printed before the WorkflowBuildError, not suppressed.
  • Unresolved built-in steps — temporarily rename node_modules/workflow to node_modules/workflow-bak:

    mv node_modules/workflow node_modules/workflow-bak
    cd workbench/nextjs-turbopack && pnpm build
    mv ../../node_modules/workflow-bak ../../node_modules/workflow # restore

    Expect:

    • WorkflowBuildError: "Failed to resolve built-in steps sources."
    • hint: run \pnpm install workflow` to resolve this issue.`
    • cause: preserves the underlying resolution error.
  • Empty workflow directory — move all your workflow files aside (or create a fresh workspace with none):

    mkdir /tmp/wf-empty &&cd /tmp/wf-empty
    # set up minimal package + workflow config with an empty workflows/ dir
    pnpm workflow build

    Or: delete all "use workflow" / "use step" directives from your files. Expect:

    • WorkflowBuildError: "No output files generated from esbuild"
    • hint mentions "use workflow" / "use step" directives.
  • .is() discriminator — in a scratch script:

    import{WorkflowBuildError}from'@workflow/errors';conste=newWorkflowBuildError('x',{hint: 'y'});console.log(WorkflowBuildError.is(e));// trueconsole.log(WorkflowBuildError.is(newError('x')));// false
  • Hint renders below a blank line — verify the hint output appears after a blank line, not jammed onto the title line (visual formatting check).

  • Runtime paths unaffected — run a normal workflow at runtime (pnpm dev and trigger a workflow). Confirm no WorkflowBuildError shows up at runtime; this class should only appear in build output.

Unit tests

  • pnpm --filter @workflow/errors test — 19 total (4 new WorkflowBuildError tests)
  • pnpm --filter @workflow/builders typecheck + test (129 pass)

📚 Friendlier errors stack

Multi-PR initiative inspired by @Schniz's stalled #706:

#PRPhaseSummary
1#1831Phase 1 + 2Ansi rendering primitives + context-violation errors
2#1832Phase 3Structured logger metadata; folds in #1812
3#1836Phase 4SerializationError at serialization / stream / encryption boundaries
4#1837Phase 5Presentation-only user vs SDK attribution (describeError)
5#1838Phase 6Consistency pass on remaining bare throw new Error(...) sites
6#1839Phase 7 foundationData-driven describeRunError + public subpath
7→ this PR (#1840)Phase 8WorkflowBuildError + applications in @workflow/builders
8#1849FollowupsDrop functionName leak, simplify docs framing, redirect stack to user code

Each PR is stacked on the previous one; merge in order.

🤖 Generated with Claude Code

@vercel

vercelBot commented Apr 23, 2026

Copy link
Copy Markdown
Contributor

CopilotAI review requested due to automatic review settings April 23, 2026 16:54
@github-actions

github-actionsBot commented Apr 23, 2026

Copy link
Copy Markdown
Contributor

🧪 E2E Test Results

Some tests failed

Summary

PassedFailedSkippedTotal
❌ 💻 Local Development10522861140
✅ 📦 Local Production10540861140
✅ 🐘 Local Postgres10540861140
✅ 🪟 Windows950095
✅ 📋 Other267018285
Total352222763800

❌ Failed Tests

💻 Local Development (2 failed)

vite-stable (2 failed):

  • error handling error propagation step errors basic step error preserves message and stack trace
  • error handling error propagation step errors cross-file step error preserves message and function names in stack

Details by Category

❌ 💻 Local Development
AppPassedFailedSkipped
✅ astro-stable8906
✅ express-stable8906
✅ fastify-stable8906
✅ hono-stable8906
✅ nextjs-turbopack-canary76019
✅ nextjs-turbopack-stable9500
✅ nextjs-webpack-canary76019
✅ nextjs-webpack-stable9500
✅ nitro-stable8906
✅ nuxt-stable8906
✅ sveltekit-stable8906
❌ vite-stable8726
✅ 📦 Local Production
AppPassedFailedSkipped
✅ astro-stable8906
✅ express-stable8906
✅ fastify-stable8906
✅ hono-stable8906
✅ nextjs-turbopack-canary76019
✅ nextjs-turbopack-stable9500
✅ nextjs-webpack-canary76019
✅ nextjs-webpack-stable9500
✅ nitro-stable8906
✅ nuxt-stable8906
✅ sveltekit-stable8906
✅ vite-stable8906
✅ 🐘 Local Postgres
AppPassedFailedSkipped
✅ astro-stable8906
✅ express-stable8906
✅ fastify-stable8906
✅ hono-stable8906
✅ nextjs-turbopack-canary76019
✅ nextjs-turbopack-stable9500
✅ nextjs-webpack-canary76019
✅ nextjs-webpack-stable9500
✅ nitro-stable8906
✅ nuxt-stable8906
✅ sveltekit-stable8906
✅ vite-stable8906
✅ 🪟 Windows
AppPassedFailedSkipped
✅ nextjs-turbopack9500
✅ 📋 Other
AppPassedFailedSkipped
✅ e2e-local-dev-nest-stable8906
✅ e2e-local-postgres-nest-stable8906
✅ e2e-local-prod-nest-stable8906

📋 View full workflow run


Some E2E test jobs failed:

  • Vercel Prod: failure
  • Local Dev: failure
  • Local Prod: success
  • Local Postgres: success
  • Windows: success

Check the workflow run for details.

@changeset-bot

changeset-botBot commented Apr 23, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: efaba3a

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

This PR includes changesets to release 21 packages
NameType
@workflow/errorsPatch
@workflow/buildersPatch
@workflow/cliPatch
@workflow/corePatch
@workflow/webPatch
workflowPatch
@workflow/world-localPatch
@workflow/world-postgresPatch
@workflow/world-vercelPatch
@workflow/astroPatch
@workflow/nestPatch
@workflow/nextPatch
@workflow/nitroPatch
@workflow/rollupPatch
@workflow/sveltekitPatch
@workflow/vitePatch
@workflow/vitestPatch
@workflow/world-testingPatch
@workflow/web-sharedPatch
@workflow/aiPatch
@workflow/nuxtPatch

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

CopilotAI 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

This PR extends the “friendlier errors” initiative into build-time by introducing a dedicated WorkflowBuildError (with an optional hint) in @workflow/errors and switching key @workflow/builders failure sites to throw it for more actionable build output.

Changes:

  • Add WorkflowBuildError (with hint and .is() discriminator) to @workflow/errors.
  • Update @workflow/builders to throw WorkflowBuildError for esbuild failures, unresolved built-in steps, and empty esbuild output, including user-action hints.
  • Add tests for WorkflowBuildError and publish a changeset for the patch releases.

Reviewed changes

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

FileDescription
packages/errors/src/index.tsAdds WorkflowBuildError class and documentation.
packages/errors/src/build-error.test.tsAdds vitest coverage for WorkflowBuildError behavior.
packages/builders/src/base-builder.tsReplaces generic Error throws with WorkflowBuildError + hints at key build failure sites.
.changeset/friendlier-build-errors.mdDeclares patch releases for @workflow/errors and @workflow/builders.

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

throw new WorkflowBuildError(
`${chalk.red('Failed to resolve built-in steps sources.')}\n\nCaused by: ${chalk.red(String(err))}`,
{
hint: `${chalk.yellow.bold('hint:')} run \`${chalk.cyan.italic('npm install workflow')}\` to resolve this issue.`,

CopilotAIApr 23, 2026

Copy link

Choose a reason for hiding this comment

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

options.hint is stored on the error (and appended to the message). Including a formatted hint: label + Chalk styling inside the hint field makes the hint harder to re-render in other contexts (e.g. structured UI/JSON) and can lead to double “hint:” prefixes. Consider keeping hint as plain text (no label/styling) and applying formatting at the presentation layer (or using @workflow/errors Ansi helpers if appropriate).

Suggested change
hint: `${chalk.yellow.bold('hint:')}run \`${chalk.cyan.italic('npm install workflow')}\` to resolve this issue.`,
hint: 'run `npm install workflow` to resolve this issue.',

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Fixed in efaba3ahint is now stored as plain text ('run \pnpm install workflow` to resolve this issue.') without the hint:label or chalk styling. Per the updated JSDoc onWorkflowBuildError`, the rendering layer is responsible for styling + any "hint:" label. I also stripped the chalk wrappers from the message string in the same throw so it renders cleanly in non-TTY contexts (CI logs, structured serialization).

Comment threadpackages/errors/src/index.ts Outdated
* by the workflow engine) — `WorkflowBuildError` fires during `pnpm build`,
* `next build`, or equivalent, before any workflow has started executing.
*
* Prefer attaching a short, actionable `hint` (e.g. `run \`npm install workflow\``)

CopilotAIApr 23, 2026

Copy link

Choose a reason for hiding this comment

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

The JSDoc example for hint uses npm install workflow, but other new/updated text in this PR uses pnpm install workflow. Please align this example with the recommended guidance (or switch to a package-manager-agnostic example) so docs and error hints don’t conflict.

Suggested change
*Preferattachingashort,actionable`hint`(e.g.`run \`npm install workflow\``)
*Preferattachingashort,actionable`hint`(e.g.`run \`pnpm install workflow\``)

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Fixed in efaba3a — JSDoc example now uses pnpm install workflow, matching the test and the actual call site.

Comment on lines +14 to +20
hint: 'run `pnpm install workflow` and try again',
});
expect(err.hint).toBe('run `pnpm install workflow` and try again');
expect(err.message).toMatchInlineSnapshot(`
"Build failed during steps

run \`pnpm install workflow\` and try again"

CopilotAIApr 23, 2026

Copy link

Choose a reason for hiding this comment

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

This test uses pnpm install workflow in the sample hint string, while some other new hints/docs in this PR use npm install workflow. If the intent is to be package-manager-agnostic (or to standardize on one), consider updating the test string accordingly so it doesn’t implicitly encode the chosen guidance.

Suggested change
hint: 'run `pnpm install workflow` and try again',
});
expect(err.hint).toBe('run `pnpm install workflow` and try again');
expect(err.message).toMatchInlineSnapshot(`
"Build failed during steps
run \`pnpm install workflow\` andtryagain"
hint: 'run `npm install workflow` and try again',
});
expect(err.hint).toBe('run `npm install workflow` and try again');
expect(err.message).toMatchInlineSnapshot(`
"Build failed during steps
run \`npm install workflow\` andtryagain"

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Fixed in efaba3a — all three sites (the hint in base-builder.ts, this test, and the WorkflowBuildError JSDoc example in packages/errors/src/index.ts) now use pnpm install workflow.

throw new WorkflowBuildError(
`${chalk.red('Failed to resolve built-in steps sources.')}\n\nCaused by: ${chalk.red(String(err))}`,
{
hint: `${chalk.yellow.bold('hint:')} run \`${chalk.cyan.italic('npm install workflow')}\` to resolve this issue.`,

CopilotAIApr 23, 2026

Copy link

Choose a reason for hiding this comment

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

The hint text here hard-codes npm install workflow, but elsewhere in this PR (e.g. WorkflowBuildError docs/tests) the guidance mentions pnpm install workflow. Please standardize the suggested command across the repo (or make it package-manager-agnostic, e.g. “install the workflow package”) to avoid confusing users.

Suggested change
hint: `${chalk.yellow.bold('hint:')}run \`${chalk.cyan.italic('npm install workflow')}\` to resolve this issue.`,
hint: `${chalk.yellow.bold('hint:')}install the \`${chalk.cyan.italic('workflow')}\` package to resolve this issue.`,

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Fixed in efaba3a — the hint now reads run \pnpm install workflow` to resolve this issue.` (standardized on pnpm across the hint string, the test, and the JSDoc example).

Add `WorkflowBuildError` class in `@workflow/errors` with optional `hint`
for an actionable next step, and apply it in `@workflow/builders` at
user-facing sites: failed esbuild phases, unresolved built-in steps, and
empty esbuild output now throw `WorkflowBuildError` with a hint pointing
at the likely fix. Runtime invariants remain plain `Error`.
@pranaygp

Copy link
Copy Markdown
ContributorAuthor

Superseded by #1849 — consolidated friendlier-errors PR with all 8 phases + follow-up fixes (ANSI leak, non-retry semantics, shared captureStackTrace helper).

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@pranaygp
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Friendlier build-time errors: WorkflowBuildError + builders sites by pranaygp · Pull Request #1840 · vercel/workflow · GitHub
Skip to content

Friendlier build-time errors: WorkflowBuildError + builders sites - #1840

Closed
pranaygp wants to merge 1 commit into
pranaygp/friendlier-errors-phase-7-observabilityfrom
pranaygp/friendlier-errors-phase-8-build-time
Closed

Friendlier build-time errors: WorkflowBuildError + builders sites#1840
pranaygp wants to merge 1 commit into
pranaygp/friendlier-errors-phase-7-observabilityfrom
pranaygp/friendlier-errors-phase-8-build-time

Conversation

@pranaygp

@pranaygppranaygp commented Apr 23, 2026

Copy link
Copy Markdown
Contributor

Summary

Phase 8 (final) of the friendlier-errors stack — extends the error-quality work from runtime into build-time.

  • Adds WorkflowBuildError in @workflow/errors with an optional hint field (appended after a blank line) and a .is() discriminator.
  • Applies it at user-facing sites in @workflow/builders/base-builder.ts:
    • Failed esbuild phases → hint at the likely fix for the phase
    • Unresolved built-in steps → hint at pnpm install workflow
    • Empty esbuild output → hint that workflow files need "use workflow" / "use step" directives
  • Internal runtime invariants remain plain Error.

Scope note: deliberately kept to @workflow/builders (ESM). Extending WorkflowBuildError into @workflow/next (CJS) needs a dynamic-import bridge similar to the existing eval('import("@workflow/builders")') pattern — can follow up in a separate PR.

Manual test plan

All tests here exercise the build pipeline, not the runtime. Use workbench/nextjs-turbopack and run pnpm build (not pnpm dev).

  • Syntax error in a workflow file → failed esbuild phase:

    // workbench/nextjs-turbopack/app/_workflows/broken.ts'use workflow';exportasyncfunctionbroken(thisisnotvalidts

    Run pnpm build. Expect in build output:

    • WorkflowBuildError with title mentioning the phase (e.g. "Build failed during workflows bundle").
    • A blank line, then hint: Review the esbuild errors above — they come from the workflows bundle. Fix the offending source files and re-run the build.
    • The original esbuild error messages printed before the WorkflowBuildError, not suppressed.
  • Unresolved built-in steps — temporarily rename node_modules/workflow to node_modules/workflow-bak:

    mv node_modules/workflow node_modules/workflow-bak
    cd workbench/nextjs-turbopack && pnpm build
    mv ../../node_modules/workflow-bak ../../node_modules/workflow # restore

    Expect:

    • WorkflowBuildError: "Failed to resolve built-in steps sources."
    • hint: run \pnpm install workflow` to resolve this issue.`
    • cause: preserves the underlying resolution error.
  • Empty workflow directory — move all your workflow files aside (or create a fresh workspace with none):

    mkdir /tmp/wf-empty &&cd /tmp/wf-empty
    # set up minimal package + workflow config with an empty workflows/ dir
    pnpm workflow build

    Or: delete all "use workflow" / "use step" directives from your files. Expect:

    • WorkflowBuildError: "No output files generated from esbuild"
    • hint mentions "use workflow" / "use step" directives.
  • .is() discriminator — in a scratch script:

    import{WorkflowBuildError}from'@workflow/errors';conste=newWorkflowBuildError('x',{hint: 'y'});console.log(WorkflowBuildError.is(e));// trueconsole.log(WorkflowBuildError.is(newError('x')));// false
  • Hint renders below a blank line — verify the hint output appears after a blank line, not jammed onto the title line (visual formatting check).

  • Runtime paths unaffected — run a normal workflow at runtime (pnpm dev and trigger a workflow). Confirm no WorkflowBuildError shows up at runtime; this class should only appear in build output.

Unit tests

  • pnpm --filter @workflow/errors test — 19 total (4 new WorkflowBuildError tests)
  • pnpm --filter @workflow/builders typecheck + test (129 pass)

📚 Friendlier errors stack

Multi-PR initiative inspired by @Schniz's stalled #706:

#PRPhaseSummary
1#1831Phase 1 + 2Ansi rendering primitives + context-violation errors
2#1832Phase 3Structured logger metadata; folds in #1812
3#1836Phase 4SerializationError at serialization / stream / encryption boundaries
4#1837Phase 5Presentation-only user vs SDK attribution (describeError)
5#1838Phase 6Consistency pass on remaining bare throw new Error(...) sites
6#1839Phase 7 foundationData-driven describeRunError + public subpath
7→ this PR (#1840)Phase 8WorkflowBuildError + applications in @workflow/builders
8#1849FollowupsDrop functionName leak, simplify docs framing, redirect stack to user code

Each PR is stacked on the previous one; merge in order.

🤖 Generated with Claude Code

@vercel

vercelBot commented Apr 23, 2026

Copy link
Copy Markdown
Contributor

CopilotAI review requested due to automatic review settings April 23, 2026 16:54
@github-actions

github-actionsBot commented Apr 23, 2026

Copy link
Copy Markdown
Contributor

🧪 E2E Test Results

Some tests failed

Summary

PassedFailedSkippedTotal
❌ 💻 Local Development10522861140
✅ 📦 Local Production10540861140
✅ 🐘 Local Postgres10540861140
✅ 🪟 Windows950095
✅ 📋 Other267018285
Total352222763800

❌ Failed Tests

💻 Local Development (2 failed)

vite-stable (2 failed):

  • error handling error propagation step errors basic step error preserves message and stack trace
  • error handling error propagation step errors cross-file step error preserves message and function names in stack

Details by Category

❌ 💻 Local Development
AppPassedFailedSkipped
✅ astro-stable8906
✅ express-stable8906
✅ fastify-stable8906
✅ hono-stable8906
✅ nextjs-turbopack-canary76019
✅ nextjs-turbopack-stable9500
✅ nextjs-webpack-canary76019
✅ nextjs-webpack-stable9500
✅ nitro-stable8906
✅ nuxt-stable8906
✅ sveltekit-stable8906
❌ vite-stable8726
✅ 📦 Local Production
AppPassedFailedSkipped
✅ astro-stable8906
✅ express-stable8906
✅ fastify-stable8906
✅ hono-stable8906
✅ nextjs-turbopack-canary76019
✅ nextjs-turbopack-stable9500
✅ nextjs-webpack-canary76019
✅ nextjs-webpack-stable9500
✅ nitro-stable8906
✅ nuxt-stable8906
✅ sveltekit-stable8906
✅ vite-stable8906
✅ 🐘 Local Postgres
AppPassedFailedSkipped
✅ astro-stable8906
✅ express-stable8906
✅ fastify-stable8906
✅ hono-stable8906
✅ nextjs-turbopack-canary76019
✅ nextjs-turbopack-stable9500
✅ nextjs-webpack-canary76019
✅ nextjs-webpack-stable9500
✅ nitro-stable8906
✅ nuxt-stable8906
✅ sveltekit-stable8906
✅ vite-stable8906
✅ 🪟 Windows
AppPassedFailedSkipped
✅ nextjs-turbopack9500
✅ 📋 Other
AppPassedFailedSkipped
✅ e2e-local-dev-nest-stable8906
✅ e2e-local-postgres-nest-stable8906
✅ e2e-local-prod-nest-stable8906

📋 View full workflow run


Some E2E test jobs failed:

  • Vercel Prod: failure
  • Local Dev: failure
  • Local Prod: success
  • Local Postgres: success
  • Windows: success

Check the workflow run for details.

@changeset-bot

changeset-botBot commented Apr 23, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: efaba3a

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

This PR includes changesets to release 21 packages
NameType
@workflow/errorsPatch
@workflow/buildersPatch
@workflow/cliPatch
@workflow/corePatch
@workflow/webPatch
workflowPatch
@workflow/world-localPatch
@workflow/world-postgresPatch
@workflow/world-vercelPatch
@workflow/astroPatch
@workflow/nestPatch
@workflow/nextPatch
@workflow/nitroPatch
@workflow/rollupPatch
@workflow/sveltekitPatch
@workflow/vitePatch
@workflow/vitestPatch
@workflow/world-testingPatch
@workflow/web-sharedPatch
@workflow/aiPatch
@workflow/nuxtPatch

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

CopilotAI 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

This PR extends the “friendlier errors” initiative into build-time by introducing a dedicated WorkflowBuildError (with an optional hint) in @workflow/errors and switching key @workflow/builders failure sites to throw it for more actionable build output.

Changes:

  • Add WorkflowBuildError (with hint and .is() discriminator) to @workflow/errors.
  • Update @workflow/builders to throw WorkflowBuildError for esbuild failures, unresolved built-in steps, and empty esbuild output, including user-action hints.
  • Add tests for WorkflowBuildError and publish a changeset for the patch releases.

Reviewed changes

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

FileDescription
packages/errors/src/index.tsAdds WorkflowBuildError class and documentation.
packages/errors/src/build-error.test.tsAdds vitest coverage for WorkflowBuildError behavior.
packages/builders/src/base-builder.tsReplaces generic Error throws with WorkflowBuildError + hints at key build failure sites.
.changeset/friendlier-build-errors.mdDeclares patch releases for @workflow/errors and @workflow/builders.

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

throw new WorkflowBuildError(
`${chalk.red('Failed to resolve built-in steps sources.')}\n\nCaused by: ${chalk.red(String(err))}`,
{
hint: `${chalk.yellow.bold('hint:')} run \`${chalk.cyan.italic('npm install workflow')}\` to resolve this issue.`,

CopilotAIApr 23, 2026

Copy link

Choose a reason for hiding this comment

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

options.hint is stored on the error (and appended to the message). Including a formatted hint: label + Chalk styling inside the hint field makes the hint harder to re-render in other contexts (e.g. structured UI/JSON) and can lead to double “hint:” prefixes. Consider keeping hint as plain text (no label/styling) and applying formatting at the presentation layer (or using @workflow/errors Ansi helpers if appropriate).

Suggested change
hint: `${chalk.yellow.bold('hint:')}run \`${chalk.cyan.italic('npm install workflow')}\` to resolve this issue.`,
hint: 'run `npm install workflow` to resolve this issue.',

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Fixed in efaba3ahint is now stored as plain text ('run \pnpm install workflow` to resolve this issue.') without the hint:label or chalk styling. Per the updated JSDoc onWorkflowBuildError`, the rendering layer is responsible for styling + any "hint:" label. I also stripped the chalk wrappers from the message string in the same throw so it renders cleanly in non-TTY contexts (CI logs, structured serialization).

Comment threadpackages/errors/src/index.ts Outdated
* by the workflow engine) — `WorkflowBuildError` fires during `pnpm build`,
* `next build`, or equivalent, before any workflow has started executing.
*
* Prefer attaching a short, actionable `hint` (e.g. `run \`npm install workflow\``)

CopilotAIApr 23, 2026

Copy link

Choose a reason for hiding this comment

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

The JSDoc example for hint uses npm install workflow, but other new/updated text in this PR uses pnpm install workflow. Please align this example with the recommended guidance (or switch to a package-manager-agnostic example) so docs and error hints don’t conflict.

Suggested change
*Preferattachingashort,actionable`hint`(e.g.`run \`npm install workflow\``)
*Preferattachingashort,actionable`hint`(e.g.`run \`pnpm install workflow\``)

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Fixed in efaba3a — JSDoc example now uses pnpm install workflow, matching the test and the actual call site.

Comment on lines +14 to +20
hint: 'run `pnpm install workflow` and try again',
});
expect(err.hint).toBe('run `pnpm install workflow` and try again');
expect(err.message).toMatchInlineSnapshot(`
"Build failed during steps

run \`pnpm install workflow\` and try again"

CopilotAIApr 23, 2026

Copy link

Choose a reason for hiding this comment

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

This test uses pnpm install workflow in the sample hint string, while some other new hints/docs in this PR use npm install workflow. If the intent is to be package-manager-agnostic (or to standardize on one), consider updating the test string accordingly so it doesn’t implicitly encode the chosen guidance.

Suggested change
hint: 'run `pnpm install workflow` and try again',
});
expect(err.hint).toBe('run `pnpm install workflow` and try again');
expect(err.message).toMatchInlineSnapshot(`
"Build failed during steps
run \`pnpm install workflow\` andtryagain"
hint: 'run `npm install workflow` and try again',
});
expect(err.hint).toBe('run `npm install workflow` and try again');
expect(err.message).toMatchInlineSnapshot(`
"Build failed during steps
run \`npm install workflow\` andtryagain"

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Fixed in efaba3a — all three sites (the hint in base-builder.ts, this test, and the WorkflowBuildError JSDoc example in packages/errors/src/index.ts) now use pnpm install workflow.

throw new WorkflowBuildError(
`${chalk.red('Failed to resolve built-in steps sources.')}\n\nCaused by: ${chalk.red(String(err))}`,
{
hint: `${chalk.yellow.bold('hint:')} run \`${chalk.cyan.italic('npm install workflow')}\` to resolve this issue.`,

CopilotAIApr 23, 2026

Copy link

Choose a reason for hiding this comment

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

The hint text here hard-codes npm install workflow, but elsewhere in this PR (e.g. WorkflowBuildError docs/tests) the guidance mentions pnpm install workflow. Please standardize the suggested command across the repo (or make it package-manager-agnostic, e.g. “install the workflow package”) to avoid confusing users.

Suggested change
hint: `${chalk.yellow.bold('hint:')}run \`${chalk.cyan.italic('npm install workflow')}\` to resolve this issue.`,
hint: `${chalk.yellow.bold('hint:')}install the \`${chalk.cyan.italic('workflow')}\` package to resolve this issue.`,

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Fixed in efaba3a — the hint now reads run \pnpm install workflow` to resolve this issue.` (standardized on pnpm across the hint string, the test, and the JSDoc example).

Add `WorkflowBuildError` class in `@workflow/errors` with optional `hint`
for an actionable next step, and apply it in `@workflow/builders` at
user-facing sites: failed esbuild phases, unresolved built-in steps, and
empty esbuild output now throw `WorkflowBuildError` with a hint pointing
at the likely fix. Runtime invariants remain plain `Error`.
@pranaygp

Copy link
Copy Markdown
ContributorAuthor

Superseded by #1849 — consolidated friendlier-errors PR with all 8 phases + follow-up fixes (ANSI leak, non-retry semantics, shared captureStackTrace helper).

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@pranaygp
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' Friendlier build-time errors: WorkflowBuildError + builders sites by pranaygp · Pull Request #1840 · vercel/workflow · GitHub
Skip to content

Friendlier build-time errors: WorkflowBuildError + builders sites - #1840

Closed
pranaygp wants to merge 1 commit into
pranaygp/friendlier-errors-phase-7-observabilityfrom
pranaygp/friendlier-errors-phase-8-build-time
Closed

Friendlier build-time errors: WorkflowBuildError + builders sites#1840
pranaygp wants to merge 1 commit into
pranaygp/friendlier-errors-phase-7-observabilityfrom
pranaygp/friendlier-errors-phase-8-build-time

Conversation

@pranaygp

@pranaygppranaygp commented Apr 23, 2026

Copy link
Copy Markdown
Contributor

Summary

Phase 8 (final) of the friendlier-errors stack — extends the error-quality work from runtime into build-time.

  • Adds WorkflowBuildError in @workflow/errors with an optional hint field (appended after a blank line) and a .is() discriminator.
  • Applies it at user-facing sites in @workflow/builders/base-builder.ts:
    • Failed esbuild phases → hint at the likely fix for the phase
    • Unresolved built-in steps → hint at pnpm install workflow
    • Empty esbuild output → hint that workflow files need "use workflow" / "use step" directives
  • Internal runtime invariants remain plain Error.

Scope note: deliberately kept to @workflow/builders (ESM). Extending WorkflowBuildError into @workflow/next (CJS) needs a dynamic-import bridge similar to the existing eval('import("@workflow/builders")') pattern — can follow up in a separate PR.

Manual test plan

All tests here exercise the build pipeline, not the runtime. Use workbench/nextjs-turbopack and run pnpm build (not pnpm dev).

  • Syntax error in a workflow file → failed esbuild phase:

    // workbench/nextjs-turbopack/app/_workflows/broken.ts'use workflow';exportasyncfunctionbroken(thisisnotvalidts

    Run pnpm build. Expect in build output:

    • WorkflowBuildError with title mentioning the phase (e.g. "Build failed during workflows bundle").
    • A blank line, then hint: Review the esbuild errors above — they come from the workflows bundle. Fix the offending source files and re-run the build.
    • The original esbuild error messages printed before the WorkflowBuildError, not suppressed.
  • Unresolved built-in steps — temporarily rename node_modules/workflow to node_modules/workflow-bak:

    mv node_modules/workflow node_modules/workflow-bak
    cd workbench/nextjs-turbopack && pnpm build
    mv ../../node_modules/workflow-bak ../../node_modules/workflow # restore

    Expect:

    • WorkflowBuildError: "Failed to resolve built-in steps sources."
    • hint: run \pnpm install workflow` to resolve this issue.`
    • cause: preserves the underlying resolution error.
  • Empty workflow directory — move all your workflow files aside (or create a fresh workspace with none):

    mkdir /tmp/wf-empty &&cd /tmp/wf-empty
    # set up minimal package + workflow config with an empty workflows/ dir
    pnpm workflow build

    Or: delete all "use workflow" / "use step" directives from your files. Expect:

    • WorkflowBuildError: "No output files generated from esbuild"
    • hint mentions "use workflow" / "use step" directives.
  • .is() discriminator — in a scratch script:

    import{WorkflowBuildError}from'@workflow/errors';conste=newWorkflowBuildError('x',{hint: 'y'});console.log(WorkflowBuildError.is(e));// trueconsole.log(WorkflowBuildError.is(newError('x')));// false
  • Hint renders below a blank line — verify the hint output appears after a blank line, not jammed onto the title line (visual formatting check).

  • Runtime paths unaffected — run a normal workflow at runtime (pnpm dev and trigger a workflow). Confirm no WorkflowBuildError shows up at runtime; this class should only appear in build output.

Unit tests

  • pnpm --filter @workflow/errors test — 19 total (4 new WorkflowBuildError tests)
  • pnpm --filter @workflow/builders typecheck + test (129 pass)

📚 Friendlier errors stack

Multi-PR initiative inspired by @Schniz's stalled #706:

#PRPhaseSummary
1#1831Phase 1 + 2Ansi rendering primitives + context-violation errors
2#1832Phase 3Structured logger metadata; folds in #1812
3#1836Phase 4SerializationError at serialization / stream / encryption boundaries
4#1837Phase 5Presentation-only user vs SDK attribution (describeError)
5#1838Phase 6Consistency pass on remaining bare throw new Error(...) sites
6#1839Phase 7 foundationData-driven describeRunError + public subpath
7→ this PR (#1840)Phase 8WorkflowBuildError + applications in @workflow/builders
8#1849FollowupsDrop functionName leak, simplify docs framing, redirect stack to user code

Each PR is stacked on the previous one; merge in order.

🤖 Generated with Claude Code

@vercel

vercelBot commented Apr 23, 2026

Copy link
Copy Markdown
Contributor

CopilotAI review requested due to automatic review settings April 23, 2026 16:54
@github-actions

github-actionsBot commented Apr 23, 2026

Copy link
Copy Markdown
Contributor

🧪 E2E Test Results

Some tests failed

Summary

PassedFailedSkippedTotal
❌ 💻 Local Development10522861140
✅ 📦 Local Production10540861140
✅ 🐘 Local Postgres10540861140
✅ 🪟 Windows950095
✅ 📋 Other267018285
Total352222763800

❌ Failed Tests

💻 Local Development (2 failed)

vite-stable (2 failed):

  • error handling error propagation step errors basic step error preserves message and stack trace
  • error handling error propagation step errors cross-file step error preserves message and function names in stack

Details by Category

❌ 💻 Local Development
AppPassedFailedSkipped
✅ astro-stable8906
✅ express-stable8906
✅ fastify-stable8906
✅ hono-stable8906
✅ nextjs-turbopack-canary76019
✅ nextjs-turbopack-stable9500
✅ nextjs-webpack-canary76019
✅ nextjs-webpack-stable9500
✅ nitro-stable8906
✅ nuxt-stable8906
✅ sveltekit-stable8906
❌ vite-stable8726
✅ 📦 Local Production
AppPassedFailedSkipped
✅ astro-stable8906
✅ express-stable8906
✅ fastify-stable8906
✅ hono-stable8906
✅ nextjs-turbopack-canary76019
✅ nextjs-turbopack-stable9500
✅ nextjs-webpack-canary76019
✅ nextjs-webpack-stable9500
✅ nitro-stable8906
✅ nuxt-stable8906
✅ sveltekit-stable8906
✅ vite-stable8906
✅ 🐘 Local Postgres
AppPassedFailedSkipped
✅ astro-stable8906
✅ express-stable8906
✅ fastify-stable8906
✅ hono-stable8906
✅ nextjs-turbopack-canary76019
✅ nextjs-turbopack-stable9500
✅ nextjs-webpack-canary76019
✅ nextjs-webpack-stable9500
✅ nitro-stable8906
✅ nuxt-stable8906
✅ sveltekit-stable8906
✅ vite-stable8906
✅ 🪟 Windows
AppPassedFailedSkipped
✅ nextjs-turbopack9500
✅ 📋 Other
AppPassedFailedSkipped
✅ e2e-local-dev-nest-stable8906
✅ e2e-local-postgres-nest-stable8906
✅ e2e-local-prod-nest-stable8906

📋 View full workflow run


Some E2E test jobs failed:

  • Vercel Prod: failure
  • Local Dev: failure
  • Local Prod: success
  • Local Postgres: success
  • Windows: success

Check the workflow run for details.

@changeset-bot

changeset-botBot commented Apr 23, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: efaba3a

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

This PR includes changesets to release 21 packages
NameType
@workflow/errorsPatch
@workflow/buildersPatch
@workflow/cliPatch
@workflow/corePatch
@workflow/webPatch
workflowPatch
@workflow/world-localPatch
@workflow/world-postgresPatch
@workflow/world-vercelPatch
@workflow/astroPatch
@workflow/nestPatch
@workflow/nextPatch
@workflow/nitroPatch
@workflow/rollupPatch
@workflow/sveltekitPatch
@workflow/vitePatch
@workflow/vitestPatch
@workflow/world-testingPatch
@workflow/web-sharedPatch
@workflow/aiPatch
@workflow/nuxtPatch

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

CopilotAI 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

This PR extends the “friendlier errors” initiative into build-time by introducing a dedicated WorkflowBuildError (with an optional hint) in @workflow/errors and switching key @workflow/builders failure sites to throw it for more actionable build output.

Changes:

  • Add WorkflowBuildError (with hint and .is() discriminator) to @workflow/errors.
  • Update @workflow/builders to throw WorkflowBuildError for esbuild failures, unresolved built-in steps, and empty esbuild output, including user-action hints.
  • Add tests for WorkflowBuildError and publish a changeset for the patch releases.

Reviewed changes

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

FileDescription
packages/errors/src/index.tsAdds WorkflowBuildError class and documentation.
packages/errors/src/build-error.test.tsAdds vitest coverage for WorkflowBuildError behavior.
packages/builders/src/base-builder.tsReplaces generic Error throws with WorkflowBuildError + hints at key build failure sites.
.changeset/friendlier-build-errors.mdDeclares patch releases for @workflow/errors and @workflow/builders.

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

throw new WorkflowBuildError(
`${chalk.red('Failed to resolve built-in steps sources.')}\n\nCaused by: ${chalk.red(String(err))}`,
{
hint: `${chalk.yellow.bold('hint:')} run \`${chalk.cyan.italic('npm install workflow')}\` to resolve this issue.`,

CopilotAIApr 23, 2026

Copy link

Choose a reason for hiding this comment

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

options.hint is stored on the error (and appended to the message). Including a formatted hint: label + Chalk styling inside the hint field makes the hint harder to re-render in other contexts (e.g. structured UI/JSON) and can lead to double “hint:” prefixes. Consider keeping hint as plain text (no label/styling) and applying formatting at the presentation layer (or using @workflow/errors Ansi helpers if appropriate).

Suggested change
hint: `${chalk.yellow.bold('hint:')}run \`${chalk.cyan.italic('npm install workflow')}\` to resolve this issue.`,
hint: 'run `npm install workflow` to resolve this issue.',

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Fixed in efaba3ahint is now stored as plain text ('run \pnpm install workflow` to resolve this issue.') without the hint:label or chalk styling. Per the updated JSDoc onWorkflowBuildError`, the rendering layer is responsible for styling + any "hint:" label. I also stripped the chalk wrappers from the message string in the same throw so it renders cleanly in non-TTY contexts (CI logs, structured serialization).

Comment threadpackages/errors/src/index.ts Outdated
* by the workflow engine) — `WorkflowBuildError` fires during `pnpm build`,
* `next build`, or equivalent, before any workflow has started executing.
*
* Prefer attaching a short, actionable `hint` (e.g. `run \`npm install workflow\``)

CopilotAIApr 23, 2026

Copy link

Choose a reason for hiding this comment

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

The JSDoc example for hint uses npm install workflow, but other new/updated text in this PR uses pnpm install workflow. Please align this example with the recommended guidance (or switch to a package-manager-agnostic example) so docs and error hints don’t conflict.

Suggested change
*Preferattachingashort,actionable`hint`(e.g.`run \`npm install workflow\``)
*Preferattachingashort,actionable`hint`(e.g.`run \`pnpm install workflow\``)

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Fixed in efaba3a — JSDoc example now uses pnpm install workflow, matching the test and the actual call site.

Comment on lines +14 to +20
hint: 'run `pnpm install workflow` and try again',
});
expect(err.hint).toBe('run `pnpm install workflow` and try again');
expect(err.message).toMatchInlineSnapshot(`
"Build failed during steps

run \`pnpm install workflow\` and try again"

CopilotAIApr 23, 2026

Copy link

Choose a reason for hiding this comment

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

This test uses pnpm install workflow in the sample hint string, while some other new hints/docs in this PR use npm install workflow. If the intent is to be package-manager-agnostic (or to standardize on one), consider updating the test string accordingly so it doesn’t implicitly encode the chosen guidance.

Suggested change
hint: 'run `pnpm install workflow` and try again',
});
expect(err.hint).toBe('run `pnpm install workflow` and try again');
expect(err.message).toMatchInlineSnapshot(`
"Build failed during steps
run \`pnpm install workflow\` andtryagain"
hint: 'run `npm install workflow` and try again',
});
expect(err.hint).toBe('run `npm install workflow` and try again');
expect(err.message).toMatchInlineSnapshot(`
"Build failed during steps
run \`npm install workflow\` andtryagain"

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Fixed in efaba3a — all three sites (the hint in base-builder.ts, this test, and the WorkflowBuildError JSDoc example in packages/errors/src/index.ts) now use pnpm install workflow.

throw new WorkflowBuildError(
`${chalk.red('Failed to resolve built-in steps sources.')}\n\nCaused by: ${chalk.red(String(err))}`,
{
hint: `${chalk.yellow.bold('hint:')} run \`${chalk.cyan.italic('npm install workflow')}\` to resolve this issue.`,

CopilotAIApr 23, 2026

Copy link

Choose a reason for hiding this comment

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

The hint text here hard-codes npm install workflow, but elsewhere in this PR (e.g. WorkflowBuildError docs/tests) the guidance mentions pnpm install workflow. Please standardize the suggested command across the repo (or make it package-manager-agnostic, e.g. “install the workflow package”) to avoid confusing users.

Suggested change
hint: `${chalk.yellow.bold('hint:')}run \`${chalk.cyan.italic('npm install workflow')}\` to resolve this issue.`,
hint: `${chalk.yellow.bold('hint:')}install the \`${chalk.cyan.italic('workflow')}\` package to resolve this issue.`,

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Fixed in efaba3a — the hint now reads run \pnpm install workflow` to resolve this issue.` (standardized on pnpm across the hint string, the test, and the JSDoc example).

Add `WorkflowBuildError` class in `@workflow/errors` with optional `hint`
for an actionable next step, and apply it in `@workflow/builders` at
user-facing sites: failed esbuild phases, unresolved built-in steps, and
empty esbuild output now throw `WorkflowBuildError` with a hint pointing
at the likely fix. Runtime invariants remain plain `Error`.
@pranaygp

Copy link
Copy Markdown
ContributorAuthor

Superseded by #1849 — consolidated friendlier-errors PR with all 8 phases + follow-up fixes (ANSI leak, non-retry semantics, shared captureStackTrace helper).

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@pranaygp
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Friendlier build-time errors: WorkflowBuildError + builders sites by pranaygp · Pull Request #1840 · vercel/workflow · GitHub
Skip to content

Friendlier build-time errors: WorkflowBuildError + builders sites - #1840

Closed
pranaygp wants to merge 1 commit into
pranaygp/friendlier-errors-phase-7-observabilityfrom
pranaygp/friendlier-errors-phase-8-build-time
Closed

Friendlier build-time errors: WorkflowBuildError + builders sites#1840
pranaygp wants to merge 1 commit into
pranaygp/friendlier-errors-phase-7-observabilityfrom
pranaygp/friendlier-errors-phase-8-build-time

Conversation

@pranaygp

@pranaygppranaygp commented Apr 23, 2026

Copy link
Copy Markdown
Contributor

Summary

Phase 8 (final) of the friendlier-errors stack — extends the error-quality work from runtime into build-time.

  • Adds WorkflowBuildError in @workflow/errors with an optional hint field (appended after a blank line) and a .is() discriminator.
  • Applies it at user-facing sites in @workflow/builders/base-builder.ts:
    • Failed esbuild phases → hint at the likely fix for the phase
    • Unresolved built-in steps → hint at pnpm install workflow
    • Empty esbuild output → hint that workflow files need "use workflow" / "use step" directives
  • Internal runtime invariants remain plain Error.

Scope note: deliberately kept to @workflow/builders (ESM). Extending WorkflowBuildError into @workflow/next (CJS) needs a dynamic-import bridge similar to the existing eval('import("@workflow/builders")') pattern — can follow up in a separate PR.

Manual test plan

All tests here exercise the build pipeline, not the runtime. Use workbench/nextjs-turbopack and run pnpm build (not pnpm dev).

  • Syntax error in a workflow file → failed esbuild phase:

    // workbench/nextjs-turbopack/app/_workflows/broken.ts'use workflow';exportasyncfunctionbroken(thisisnotvalidts

    Run pnpm build. Expect in build output:

    • WorkflowBuildError with title mentioning the phase (e.g. "Build failed during workflows bundle").
    • A blank line, then hint: Review the esbuild errors above — they come from the workflows bundle. Fix the offending source files and re-run the build.
    • The original esbuild error messages printed before the WorkflowBuildError, not suppressed.
  • Unresolved built-in steps — temporarily rename node_modules/workflow to node_modules/workflow-bak:

    mv node_modules/workflow node_modules/workflow-bak
    cd workbench/nextjs-turbopack && pnpm build
    mv ../../node_modules/workflow-bak ../../node_modules/workflow # restore

    Expect:

    • WorkflowBuildError: "Failed to resolve built-in steps sources."
    • hint: run \pnpm install workflow` to resolve this issue.`
    • cause: preserves the underlying resolution error.
  • Empty workflow directory — move all your workflow files aside (or create a fresh workspace with none):

    mkdir /tmp/wf-empty &&cd /tmp/wf-empty
    # set up minimal package + workflow config with an empty workflows/ dir
    pnpm workflow build

    Or: delete all "use workflow" / "use step" directives from your files. Expect:

    • WorkflowBuildError: "No output files generated from esbuild"
    • hint mentions "use workflow" / "use step" directives.
  • .is() discriminator — in a scratch script:

    import{WorkflowBuildError}from'@workflow/errors';conste=newWorkflowBuildError('x',{hint: 'y'});console.log(WorkflowBuildError.is(e));// trueconsole.log(WorkflowBuildError.is(newError('x')));// false
  • Hint renders below a blank line — verify the hint output appears after a blank line, not jammed onto the title line (visual formatting check).

  • Runtime paths unaffected — run a normal workflow at runtime (pnpm dev and trigger a workflow). Confirm no WorkflowBuildError shows up at runtime; this class should only appear in build output.

Unit tests

  • pnpm --filter @workflow/errors test — 19 total (4 new WorkflowBuildError tests)
  • pnpm --filter @workflow/builders typecheck + test (129 pass)

📚 Friendlier errors stack

Multi-PR initiative inspired by @Schniz's stalled #706:

#PRPhaseSummary
1#1831Phase 1 + 2Ansi rendering primitives + context-violation errors
2#1832Phase 3Structured logger metadata; folds in #1812
3#1836Phase 4SerializationError at serialization / stream / encryption boundaries
4#1837Phase 5Presentation-only user vs SDK attribution (describeError)
5#1838Phase 6Consistency pass on remaining bare throw new Error(...) sites
6#1839Phase 7 foundationData-driven describeRunError + public subpath
7→ this PR (#1840)Phase 8WorkflowBuildError + applications in @workflow/builders
8#1849FollowupsDrop functionName leak, simplify docs framing, redirect stack to user code

Each PR is stacked on the previous one; merge in order.

🤖 Generated with Claude Code

@vercel

vercelBot commented Apr 23, 2026

Copy link
Copy Markdown
Contributor

CopilotAI review requested due to automatic review settings April 23, 2026 16:54
@github-actions

github-actionsBot commented Apr 23, 2026

Copy link
Copy Markdown
Contributor

🧪 E2E Test Results

Some tests failed

Summary

PassedFailedSkippedTotal
❌ 💻 Local Development10522861140
✅ 📦 Local Production10540861140
✅ 🐘 Local Postgres10540861140
✅ 🪟 Windows950095
✅ 📋 Other267018285
Total352222763800

❌ Failed Tests

💻 Local Development (2 failed)

vite-stable (2 failed):

  • error handling error propagation step errors basic step error preserves message and stack trace
  • error handling error propagation step errors cross-file step error preserves message and function names in stack

Details by Category

❌ 💻 Local Development
AppPassedFailedSkipped
✅ astro-stable8906
✅ express-stable8906
✅ fastify-stable8906
✅ hono-stable8906
✅ nextjs-turbopack-canary76019
✅ nextjs-turbopack-stable9500
✅ nextjs-webpack-canary76019
✅ nextjs-webpack-stable9500
✅ nitro-stable8906
✅ nuxt-stable8906
✅ sveltekit-stable8906
❌ vite-stable8726
✅ 📦 Local Production
AppPassedFailedSkipped
✅ astro-stable8906
✅ express-stable8906
✅ fastify-stable8906
✅ hono-stable8906
✅ nextjs-turbopack-canary76019
✅ nextjs-turbopack-stable9500
✅ nextjs-webpack-canary76019
✅ nextjs-webpack-stable9500
✅ nitro-stable8906
✅ nuxt-stable8906
✅ sveltekit-stable8906
✅ vite-stable8906
✅ 🐘 Local Postgres
AppPassedFailedSkipped
✅ astro-stable8906
✅ express-stable8906
✅ fastify-stable8906
✅ hono-stable8906
✅ nextjs-turbopack-canary76019
✅ nextjs-turbopack-stable9500
✅ nextjs-webpack-canary76019
✅ nextjs-webpack-stable9500
✅ nitro-stable8906
✅ nuxt-stable8906
✅ sveltekit-stable8906
✅ vite-stable8906
✅ 🪟 Windows
AppPassedFailedSkipped
✅ nextjs-turbopack9500
✅ 📋 Other
AppPassedFailedSkipped
✅ e2e-local-dev-nest-stable8906
✅ e2e-local-postgres-nest-stable8906
✅ e2e-local-prod-nest-stable8906

📋 View full workflow run


Some E2E test jobs failed:

  • Vercel Prod: failure
  • Local Dev: failure
  • Local Prod: success
  • Local Postgres: success
  • Windows: success

Check the workflow run for details.

@changeset-bot

changeset-botBot commented Apr 23, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: efaba3a

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

This PR includes changesets to release 21 packages
NameType
@workflow/errorsPatch
@workflow/buildersPatch
@workflow/cliPatch
@workflow/corePatch
@workflow/webPatch
workflowPatch
@workflow/world-localPatch
@workflow/world-postgresPatch
@workflow/world-vercelPatch
@workflow/astroPatch
@workflow/nestPatch
@workflow/nextPatch
@workflow/nitroPatch
@workflow/rollupPatch
@workflow/sveltekitPatch
@workflow/vitePatch
@workflow/vitestPatch
@workflow/world-testingPatch
@workflow/web-sharedPatch
@workflow/aiPatch
@workflow/nuxtPatch

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

CopilotAI 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

This PR extends the “friendlier errors” initiative into build-time by introducing a dedicated WorkflowBuildError (with an optional hint) in @workflow/errors and switching key @workflow/builders failure sites to throw it for more actionable build output.

Changes:

  • Add WorkflowBuildError (with hint and .is() discriminator) to @workflow/errors.
  • Update @workflow/builders to throw WorkflowBuildError for esbuild failures, unresolved built-in steps, and empty esbuild output, including user-action hints.
  • Add tests for WorkflowBuildError and publish a changeset for the patch releases.

Reviewed changes

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

FileDescription
packages/errors/src/index.tsAdds WorkflowBuildError class and documentation.
packages/errors/src/build-error.test.tsAdds vitest coverage for WorkflowBuildError behavior.
packages/builders/src/base-builder.tsReplaces generic Error throws with WorkflowBuildError + hints at key build failure sites.
.changeset/friendlier-build-errors.mdDeclares patch releases for @workflow/errors and @workflow/builders.

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

throw new WorkflowBuildError(
`${chalk.red('Failed to resolve built-in steps sources.')}\n\nCaused by: ${chalk.red(String(err))}`,
{
hint: `${chalk.yellow.bold('hint:')} run \`${chalk.cyan.italic('npm install workflow')}\` to resolve this issue.`,

CopilotAIApr 23, 2026

Copy link

Choose a reason for hiding this comment

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

options.hint is stored on the error (and appended to the message). Including a formatted hint: label + Chalk styling inside the hint field makes the hint harder to re-render in other contexts (e.g. structured UI/JSON) and can lead to double “hint:” prefixes. Consider keeping hint as plain text (no label/styling) and applying formatting at the presentation layer (or using @workflow/errors Ansi helpers if appropriate).

Suggested change
hint: `${chalk.yellow.bold('hint:')}run \`${chalk.cyan.italic('npm install workflow')}\` to resolve this issue.`,
hint: 'run `npm install workflow` to resolve this issue.',

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Fixed in efaba3ahint is now stored as plain text ('run \pnpm install workflow` to resolve this issue.') without the hint:label or chalk styling. Per the updated JSDoc onWorkflowBuildError`, the rendering layer is responsible for styling + any "hint:" label. I also stripped the chalk wrappers from the message string in the same throw so it renders cleanly in non-TTY contexts (CI logs, structured serialization).

Comment threadpackages/errors/src/index.ts Outdated
* by the workflow engine) — `WorkflowBuildError` fires during `pnpm build`,
* `next build`, or equivalent, before any workflow has started executing.
*
* Prefer attaching a short, actionable `hint` (e.g. `run \`npm install workflow\``)

CopilotAIApr 23, 2026

Copy link

Choose a reason for hiding this comment

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

The JSDoc example for hint uses npm install workflow, but other new/updated text in this PR uses pnpm install workflow. Please align this example with the recommended guidance (or switch to a package-manager-agnostic example) so docs and error hints don’t conflict.

Suggested change
*Preferattachingashort,actionable`hint`(e.g.`run \`npm install workflow\``)
*Preferattachingashort,actionable`hint`(e.g.`run \`pnpm install workflow\``)

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Fixed in efaba3a — JSDoc example now uses pnpm install workflow, matching the test and the actual call site.

Comment on lines +14 to +20
hint: 'run `pnpm install workflow` and try again',
});
expect(err.hint).toBe('run `pnpm install workflow` and try again');
expect(err.message).toMatchInlineSnapshot(`
"Build failed during steps

run \`pnpm install workflow\` and try again"

CopilotAIApr 23, 2026

Copy link

Choose a reason for hiding this comment

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

This test uses pnpm install workflow in the sample hint string, while some other new hints/docs in this PR use npm install workflow. If the intent is to be package-manager-agnostic (or to standardize on one), consider updating the test string accordingly so it doesn’t implicitly encode the chosen guidance.

Suggested change
hint: 'run `pnpm install workflow` and try again',
});
expect(err.hint).toBe('run `pnpm install workflow` and try again');
expect(err.message).toMatchInlineSnapshot(`
"Build failed during steps
run \`pnpm install workflow\` andtryagain"
hint: 'run `npm install workflow` and try again',
});
expect(err.hint).toBe('run `npm install workflow` and try again');
expect(err.message).toMatchInlineSnapshot(`
"Build failed during steps
run \`npm install workflow\` andtryagain"

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Fixed in efaba3a — all three sites (the hint in base-builder.ts, this test, and the WorkflowBuildError JSDoc example in packages/errors/src/index.ts) now use pnpm install workflow.

throw new WorkflowBuildError(
`${chalk.red('Failed to resolve built-in steps sources.')}\n\nCaused by: ${chalk.red(String(err))}`,
{
hint: `${chalk.yellow.bold('hint:')} run \`${chalk.cyan.italic('npm install workflow')}\` to resolve this issue.`,

CopilotAIApr 23, 2026

Copy link

Choose a reason for hiding this comment

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

The hint text here hard-codes npm install workflow, but elsewhere in this PR (e.g. WorkflowBuildError docs/tests) the guidance mentions pnpm install workflow. Please standardize the suggested command across the repo (or make it package-manager-agnostic, e.g. “install the workflow package”) to avoid confusing users.

Suggested change
hint: `${chalk.yellow.bold('hint:')}run \`${chalk.cyan.italic('npm install workflow')}\` to resolve this issue.`,
hint: `${chalk.yellow.bold('hint:')}install the \`${chalk.cyan.italic('workflow')}\` package to resolve this issue.`,

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Fixed in efaba3a — the hint now reads run \pnpm install workflow` to resolve this issue.` (standardized on pnpm across the hint string, the test, and the JSDoc example).

Add `WorkflowBuildError` class in `@workflow/errors` with optional `hint`
for an actionable next step, and apply it in `@workflow/builders` at
user-facing sites: failed esbuild phases, unresolved built-in steps, and
empty esbuild output now throw `WorkflowBuildError` with a hint pointing
at the likely fix. Runtime invariants remain plain `Error`.
@pranaygp

Copy link
Copy Markdown
ContributorAuthor

Superseded by #1849 — consolidated friendlier-errors PR with all 8 phases + follow-up fixes (ANSI leak, non-retry semantics, shared captureStackTrace helper).

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@pranaygp
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Friendlier build-time errors: WorkflowBuildError + builders sites by pranaygp · Pull Request #1840 · vercel/workflow · GitHub
Skip to content

Friendlier build-time errors: WorkflowBuildError + builders sites - #1840

Closed
pranaygp wants to merge 1 commit into
pranaygp/friendlier-errors-phase-7-observabilityfrom
pranaygp/friendlier-errors-phase-8-build-time
Closed

Friendlier build-time errors: WorkflowBuildError + builders sites#1840
pranaygp wants to merge 1 commit into
pranaygp/friendlier-errors-phase-7-observabilityfrom
pranaygp/friendlier-errors-phase-8-build-time

Conversation

@pranaygp

@pranaygppranaygp commented Apr 23, 2026

Copy link
Copy Markdown
Contributor

Summary

Phase 8 (final) of the friendlier-errors stack — extends the error-quality work from runtime into build-time.

  • Adds WorkflowBuildError in @workflow/errors with an optional hint field (appended after a blank line) and a .is() discriminator.
  • Applies it at user-facing sites in @workflow/builders/base-builder.ts:
    • Failed esbuild phases → hint at the likely fix for the phase
    • Unresolved built-in steps → hint at pnpm install workflow
    • Empty esbuild output → hint that workflow files need "use workflow" / "use step" directives
  • Internal runtime invariants remain plain Error.

Scope note: deliberately kept to @workflow/builders (ESM). Extending WorkflowBuildError into @workflow/next (CJS) needs a dynamic-import bridge similar to the existing eval('import("@workflow/builders")') pattern — can follow up in a separate PR.

Manual test plan

All tests here exercise the build pipeline, not the runtime. Use workbench/nextjs-turbopack and run pnpm build (not pnpm dev).

  • Syntax error in a workflow file → failed esbuild phase:

    // workbench/nextjs-turbopack/app/_workflows/broken.ts'use workflow';exportasyncfunctionbroken(thisisnotvalidts

    Run pnpm build. Expect in build output:

    • WorkflowBuildError with title mentioning the phase (e.g. "Build failed during workflows bundle").
    • A blank line, then hint: Review the esbuild errors above — they come from the workflows bundle. Fix the offending source files and re-run the build.
    • The original esbuild error messages printed before the WorkflowBuildError, not suppressed.
  • Unresolved built-in steps — temporarily rename node_modules/workflow to node_modules/workflow-bak:

    mv node_modules/workflow node_modules/workflow-bak
    cd workbench/nextjs-turbopack && pnpm build
    mv ../../node_modules/workflow-bak ../../node_modules/workflow # restore

    Expect:

    • WorkflowBuildError: "Failed to resolve built-in steps sources."
    • hint: run \pnpm install workflow` to resolve this issue.`
    • cause: preserves the underlying resolution error.
  • Empty workflow directory — move all your workflow files aside (or create a fresh workspace with none):

    mkdir /tmp/wf-empty &&cd /tmp/wf-empty
    # set up minimal package + workflow config with an empty workflows/ dir
    pnpm workflow build

    Or: delete all "use workflow" / "use step" directives from your files. Expect:

    • WorkflowBuildError: "No output files generated from esbuild"
    • hint mentions "use workflow" / "use step" directives.
  • .is() discriminator — in a scratch script:

    import{WorkflowBuildError}from'@workflow/errors';conste=newWorkflowBuildError('x',{hint: 'y'});console.log(WorkflowBuildError.is(e));// trueconsole.log(WorkflowBuildError.is(newError('x')));// false
  • Hint renders below a blank line — verify the hint output appears after a blank line, not jammed onto the title line (visual formatting check).

  • Runtime paths unaffected — run a normal workflow at runtime (pnpm dev and trigger a workflow). Confirm no WorkflowBuildError shows up at runtime; this class should only appear in build output.

Unit tests

  • pnpm --filter @workflow/errors test — 19 total (4 new WorkflowBuildError tests)
  • pnpm --filter @workflow/builders typecheck + test (129 pass)

📚 Friendlier errors stack

Multi-PR initiative inspired by @Schniz's stalled #706:

#PRPhaseSummary
1#1831Phase 1 + 2Ansi rendering primitives + context-violation errors
2#1832Phase 3Structured logger metadata; folds in #1812
3#1836Phase 4SerializationError at serialization / stream / encryption boundaries
4#1837Phase 5Presentation-only user vs SDK attribution (describeError)
5#1838Phase 6Consistency pass on remaining bare throw new Error(...) sites
6#1839Phase 7 foundationData-driven describeRunError + public subpath
7→ this PR (#1840)Phase 8WorkflowBuildError + applications in @workflow/builders
8#1849FollowupsDrop functionName leak, simplify docs framing, redirect stack to user code

Each PR is stacked on the previous one; merge in order.

🤖 Generated with Claude Code

@vercel

vercelBot commented Apr 23, 2026

Copy link
Copy Markdown
Contributor

CopilotAI review requested due to automatic review settings April 23, 2026 16:54
@github-actions

github-actionsBot commented Apr 23, 2026

Copy link
Copy Markdown
Contributor

🧪 E2E Test Results

Some tests failed

Summary

PassedFailedSkippedTotal
❌ 💻 Local Development10522861140
✅ 📦 Local Production10540861140
✅ 🐘 Local Postgres10540861140
✅ 🪟 Windows950095
✅ 📋 Other267018285
Total352222763800

❌ Failed Tests

💻 Local Development (2 failed)

vite-stable (2 failed):

  • error handling error propagation step errors basic step error preserves message and stack trace
  • error handling error propagation step errors cross-file step error preserves message and function names in stack

Details by Category

❌ 💻 Local Development
AppPassedFailedSkipped
✅ astro-stable8906
✅ express-stable8906
✅ fastify-stable8906
✅ hono-stable8906
✅ nextjs-turbopack-canary76019
✅ nextjs-turbopack-stable9500
✅ nextjs-webpack-canary76019
✅ nextjs-webpack-stable9500
✅ nitro-stable8906
✅ nuxt-stable8906
✅ sveltekit-stable8906
❌ vite-stable8726
✅ 📦 Local Production
AppPassedFailedSkipped
✅ astro-stable8906
✅ express-stable8906
✅ fastify-stable8906
✅ hono-stable8906
✅ nextjs-turbopack-canary76019
✅ nextjs-turbopack-stable9500
✅ nextjs-webpack-canary76019
✅ nextjs-webpack-stable9500
✅ nitro-stable8906
✅ nuxt-stable8906
✅ sveltekit-stable8906
✅ vite-stable8906
✅ 🐘 Local Postgres
AppPassedFailedSkipped
✅ astro-stable8906
✅ express-stable8906
✅ fastify-stable8906
✅ hono-stable8906
✅ nextjs-turbopack-canary76019
✅ nextjs-turbopack-stable9500
✅ nextjs-webpack-canary76019
✅ nextjs-webpack-stable9500
✅ nitro-stable8906
✅ nuxt-stable8906
✅ sveltekit-stable8906
✅ vite-stable8906
✅ 🪟 Windows
AppPassedFailedSkipped
✅ nextjs-turbopack9500
✅ 📋 Other
AppPassedFailedSkipped
✅ e2e-local-dev-nest-stable8906
✅ e2e-local-postgres-nest-stable8906
✅ e2e-local-prod-nest-stable8906

📋 View full workflow run


Some E2E test jobs failed:

  • Vercel Prod: failure
  • Local Dev: failure
  • Local Prod: success
  • Local Postgres: success
  • Windows: success

Check the workflow run for details.

@changeset-bot

changeset-botBot commented Apr 23, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: efaba3a

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

This PR includes changesets to release 21 packages
NameType
@workflow/errorsPatch
@workflow/buildersPatch
@workflow/cliPatch
@workflow/corePatch
@workflow/webPatch
workflowPatch
@workflow/world-localPatch
@workflow/world-postgresPatch
@workflow/world-vercelPatch
@workflow/astroPatch
@workflow/nestPatch
@workflow/nextPatch
@workflow/nitroPatch
@workflow/rollupPatch
@workflow/sveltekitPatch
@workflow/vitePatch
@workflow/vitestPatch
@workflow/world-testingPatch
@workflow/web-sharedPatch
@workflow/aiPatch
@workflow/nuxtPatch

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

CopilotAI 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

This PR extends the “friendlier errors” initiative into build-time by introducing a dedicated WorkflowBuildError (with an optional hint) in @workflow/errors and switching key @workflow/builders failure sites to throw it for more actionable build output.

Changes:

  • Add WorkflowBuildError (with hint and .is() discriminator) to @workflow/errors.
  • Update @workflow/builders to throw WorkflowBuildError for esbuild failures, unresolved built-in steps, and empty esbuild output, including user-action hints.
  • Add tests for WorkflowBuildError and publish a changeset for the patch releases.

Reviewed changes

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

FileDescription
packages/errors/src/index.tsAdds WorkflowBuildError class and documentation.
packages/errors/src/build-error.test.tsAdds vitest coverage for WorkflowBuildError behavior.
packages/builders/src/base-builder.tsReplaces generic Error throws with WorkflowBuildError + hints at key build failure sites.
.changeset/friendlier-build-errors.mdDeclares patch releases for @workflow/errors and @workflow/builders.

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

throw new WorkflowBuildError(
`${chalk.red('Failed to resolve built-in steps sources.')}\n\nCaused by: ${chalk.red(String(err))}`,
{
hint: `${chalk.yellow.bold('hint:')} run \`${chalk.cyan.italic('npm install workflow')}\` to resolve this issue.`,

CopilotAIApr 23, 2026

Copy link

Choose a reason for hiding this comment

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

options.hint is stored on the error (and appended to the message). Including a formatted hint: label + Chalk styling inside the hint field makes the hint harder to re-render in other contexts (e.g. structured UI/JSON) and can lead to double “hint:” prefixes. Consider keeping hint as plain text (no label/styling) and applying formatting at the presentation layer (or using @workflow/errors Ansi helpers if appropriate).

Suggested change
hint: `${chalk.yellow.bold('hint:')}run \`${chalk.cyan.italic('npm install workflow')}\` to resolve this issue.`,
hint: 'run `npm install workflow` to resolve this issue.',

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Fixed in efaba3ahint is now stored as plain text ('run \pnpm install workflow` to resolve this issue.') without the hint:label or chalk styling. Per the updated JSDoc onWorkflowBuildError`, the rendering layer is responsible for styling + any "hint:" label. I also stripped the chalk wrappers from the message string in the same throw so it renders cleanly in non-TTY contexts (CI logs, structured serialization).

Comment threadpackages/errors/src/index.ts Outdated
* by the workflow engine) — `WorkflowBuildError` fires during `pnpm build`,
* `next build`, or equivalent, before any workflow has started executing.
*
* Prefer attaching a short, actionable `hint` (e.g. `run \`npm install workflow\``)

CopilotAIApr 23, 2026

Copy link

Choose a reason for hiding this comment

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

The JSDoc example for hint uses npm install workflow, but other new/updated text in this PR uses pnpm install workflow. Please align this example with the recommended guidance (or switch to a package-manager-agnostic example) so docs and error hints don’t conflict.

Suggested change
*Preferattachingashort,actionable`hint`(e.g.`run \`npm install workflow\``)
*Preferattachingashort,actionable`hint`(e.g.`run \`pnpm install workflow\``)

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Fixed in efaba3a — JSDoc example now uses pnpm install workflow, matching the test and the actual call site.

Comment on lines +14 to +20
hint: 'run `pnpm install workflow` and try again',
});
expect(err.hint).toBe('run `pnpm install workflow` and try again');
expect(err.message).toMatchInlineSnapshot(`
"Build failed during steps

run \`pnpm install workflow\` and try again"

CopilotAIApr 23, 2026

Copy link

Choose a reason for hiding this comment

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

This test uses pnpm install workflow in the sample hint string, while some other new hints/docs in this PR use npm install workflow. If the intent is to be package-manager-agnostic (or to standardize on one), consider updating the test string accordingly so it doesn’t implicitly encode the chosen guidance.

Suggested change
hint: 'run `pnpm install workflow` and try again',
});
expect(err.hint).toBe('run `pnpm install workflow` and try again');
expect(err.message).toMatchInlineSnapshot(`
"Build failed during steps
run \`pnpm install workflow\` andtryagain"
hint: 'run `npm install workflow` and try again',
});
expect(err.hint).toBe('run `npm install workflow` and try again');
expect(err.message).toMatchInlineSnapshot(`
"Build failed during steps
run \`npm install workflow\` andtryagain"

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Fixed in efaba3a — all three sites (the hint in base-builder.ts, this test, and the WorkflowBuildError JSDoc example in packages/errors/src/index.ts) now use pnpm install workflow.

throw new WorkflowBuildError(
`${chalk.red('Failed to resolve built-in steps sources.')}\n\nCaused by: ${chalk.red(String(err))}`,
{
hint: `${chalk.yellow.bold('hint:')} run \`${chalk.cyan.italic('npm install workflow')}\` to resolve this issue.`,

CopilotAIApr 23, 2026

Copy link

Choose a reason for hiding this comment

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

The hint text here hard-codes npm install workflow, but elsewhere in this PR (e.g. WorkflowBuildError docs/tests) the guidance mentions pnpm install workflow. Please standardize the suggested command across the repo (or make it package-manager-agnostic, e.g. “install the workflow package”) to avoid confusing users.

Suggested change
hint: `${chalk.yellow.bold('hint:')}run \`${chalk.cyan.italic('npm install workflow')}\` to resolve this issue.`,
hint: `${chalk.yellow.bold('hint:')}install the \`${chalk.cyan.italic('workflow')}\` package to resolve this issue.`,

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Fixed in efaba3a — the hint now reads run \pnpm install workflow` to resolve this issue.` (standardized on pnpm across the hint string, the test, and the JSDoc example).

Add `WorkflowBuildError` class in `@workflow/errors` with optional `hint`
for an actionable next step, and apply it in `@workflow/builders` at
user-facing sites: failed esbuild phases, unresolved built-in steps, and
empty esbuild output now throw `WorkflowBuildError` with a hint pointing
at the likely fix. Runtime invariants remain plain `Error`.
@pranaygp

Copy link
Copy Markdown
ContributorAuthor

Superseded by #1849 — consolidated friendlier-errors PR with all 8 phases + follow-up fixes (ANSI leak, non-retry semantics, shared captureStackTrace helper).

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@pranaygp
, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); Friendlier build-time errors: WorkflowBuildError + builders sites by pranaygp · Pull Request #1840 · vercel/workflow · GitHub
Skip to content

Friendlier build-time errors: WorkflowBuildError + builders sites - #1840

Closed
pranaygp wants to merge 1 commit into
pranaygp/friendlier-errors-phase-7-observabilityfrom
pranaygp/friendlier-errors-phase-8-build-time
Closed

Friendlier build-time errors: WorkflowBuildError + builders sites#1840
pranaygp wants to merge 1 commit into
pranaygp/friendlier-errors-phase-7-observabilityfrom
pranaygp/friendlier-errors-phase-8-build-time

Conversation

@pranaygp

@pranaygppranaygp commented Apr 23, 2026

Copy link
Copy Markdown
Contributor

Summary

Phase 8 (final) of the friendlier-errors stack — extends the error-quality work from runtime into build-time.

  • Adds WorkflowBuildError in @workflow/errors with an optional hint field (appended after a blank line) and a .is() discriminator.
  • Applies it at user-facing sites in @workflow/builders/base-builder.ts:
    • Failed esbuild phases → hint at the likely fix for the phase
    • Unresolved built-in steps → hint at pnpm install workflow
    • Empty esbuild output → hint that workflow files need "use workflow" / "use step" directives
  • Internal runtime invariants remain plain Error.

Scope note: deliberately kept to @workflow/builders (ESM). Extending WorkflowBuildError into @workflow/next (CJS) needs a dynamic-import bridge similar to the existing eval('import("@workflow/builders")') pattern — can follow up in a separate PR.

Manual test plan

All tests here exercise the build pipeline, not the runtime. Use workbench/nextjs-turbopack and run pnpm build (not pnpm dev).

  • Syntax error in a workflow file → failed esbuild phase:

    // workbench/nextjs-turbopack/app/_workflows/broken.ts'use workflow';exportasyncfunctionbroken(thisisnotvalidts

    Run pnpm build. Expect in build output:

    • WorkflowBuildError with title mentioning the phase (e.g. "Build failed during workflows bundle").
    • A blank line, then hint: Review the esbuild errors above — they come from the workflows bundle. Fix the offending source files and re-run the build.
    • The original esbuild error messages printed before the WorkflowBuildError, not suppressed.
  • Unresolved built-in steps — temporarily rename node_modules/workflow to node_modules/workflow-bak:

    mv node_modules/workflow node_modules/workflow-bak
    cd workbench/nextjs-turbopack && pnpm build
    mv ../../node_modules/workflow-bak ../../node_modules/workflow # restore

    Expect:

    • WorkflowBuildError: "Failed to resolve built-in steps sources."
    • hint: run \pnpm install workflow` to resolve this issue.`
    • cause: preserves the underlying resolution error.
  • Empty workflow directory — move all your workflow files aside (or create a fresh workspace with none):

    mkdir /tmp/wf-empty &&cd /tmp/wf-empty
    # set up minimal package + workflow config with an empty workflows/ dir
    pnpm workflow build

    Or: delete all "use workflow" / "use step" directives from your files. Expect:

    • WorkflowBuildError: "No output files generated from esbuild"
    • hint mentions "use workflow" / "use step" directives.
  • .is() discriminator — in a scratch script:

    import{WorkflowBuildError}from'@workflow/errors';conste=newWorkflowBuildError('x',{hint: 'y'});console.log(WorkflowBuildError.is(e));// trueconsole.log(WorkflowBuildError.is(newError('x')));// false
  • Hint renders below a blank line — verify the hint output appears after a blank line, not jammed onto the title line (visual formatting check).

  • Runtime paths unaffected — run a normal workflow at runtime (pnpm dev and trigger a workflow). Confirm no WorkflowBuildError shows up at runtime; this class should only appear in build output.

Unit tests

  • pnpm --filter @workflow/errors test — 19 total (4 new WorkflowBuildError tests)
  • pnpm --filter @workflow/builders typecheck + test (129 pass)

📚 Friendlier errors stack

Multi-PR initiative inspired by @Schniz's stalled #706:

#PRPhaseSummary
1#1831Phase 1 + 2Ansi rendering primitives + context-violation errors
2#1832Phase 3Structured logger metadata; folds in #1812
3#1836Phase 4SerializationError at serialization / stream / encryption boundaries
4#1837Phase 5Presentation-only user vs SDK attribution (describeError)
5#1838Phase 6Consistency pass on remaining bare throw new Error(...) sites
6#1839Phase 7 foundationData-driven describeRunError + public subpath
7→ this PR (#1840)Phase 8WorkflowBuildError + applications in @workflow/builders
8#1849FollowupsDrop functionName leak, simplify docs framing, redirect stack to user code

Each PR is stacked on the previous one; merge in order.

🤖 Generated with Claude Code

@vercel

vercelBot commented Apr 23, 2026

Copy link
Copy Markdown
Contributor

CopilotAI review requested due to automatic review settings April 23, 2026 16:54
@github-actions

github-actionsBot commented Apr 23, 2026

Copy link
Copy Markdown
Contributor

🧪 E2E Test Results

Some tests failed

Summary

PassedFailedSkippedTotal
❌ 💻 Local Development10522861140
✅ 📦 Local Production10540861140
✅ 🐘 Local Postgres10540861140
✅ 🪟 Windows950095
✅ 📋 Other267018285
Total352222763800

❌ Failed Tests

💻 Local Development (2 failed)

vite-stable (2 failed):

  • error handling error propagation step errors basic step error preserves message and stack trace
  • error handling error propagation step errors cross-file step error preserves message and function names in stack

Details by Category

❌ 💻 Local Development
AppPassedFailedSkipped
✅ astro-stable8906
✅ express-stable8906
✅ fastify-stable8906
✅ hono-stable8906
✅ nextjs-turbopack-canary76019
✅ nextjs-turbopack-stable9500
✅ nextjs-webpack-canary76019
✅ nextjs-webpack-stable9500
✅ nitro-stable8906
✅ nuxt-stable8906
✅ sveltekit-stable8906
❌ vite-stable8726
✅ 📦 Local Production
AppPassedFailedSkipped
✅ astro-stable8906
✅ express-stable8906
✅ fastify-stable8906
✅ hono-stable8906
✅ nextjs-turbopack-canary76019
✅ nextjs-turbopack-stable9500
✅ nextjs-webpack-canary76019
✅ nextjs-webpack-stable9500
✅ nitro-stable8906
✅ nuxt-stable8906
✅ sveltekit-stable8906
✅ vite-stable8906
✅ 🐘 Local Postgres
AppPassedFailedSkipped
✅ astro-stable8906
✅ express-stable8906
✅ fastify-stable8906
✅ hono-stable8906
✅ nextjs-turbopack-canary76019
✅ nextjs-turbopack-stable9500
✅ nextjs-webpack-canary76019
✅ nextjs-webpack-stable9500
✅ nitro-stable8906
✅ nuxt-stable8906
✅ sveltekit-stable8906
✅ vite-stable8906
✅ 🪟 Windows
AppPassedFailedSkipped
✅ nextjs-turbopack9500
✅ 📋 Other
AppPassedFailedSkipped
✅ e2e-local-dev-nest-stable8906
✅ e2e-local-postgres-nest-stable8906
✅ e2e-local-prod-nest-stable8906

📋 View full workflow run


Some E2E test jobs failed:

  • Vercel Prod: failure
  • Local Dev: failure
  • Local Prod: success
  • Local Postgres: success
  • Windows: success

Check the workflow run for details.

@changeset-bot

changeset-botBot commented Apr 23, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: efaba3a

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

This PR includes changesets to release 21 packages
NameType
@workflow/errorsPatch
@workflow/buildersPatch
@workflow/cliPatch
@workflow/corePatch
@workflow/webPatch
workflowPatch
@workflow/world-localPatch
@workflow/world-postgresPatch
@workflow/world-vercelPatch
@workflow/astroPatch
@workflow/nestPatch
@workflow/nextPatch
@workflow/nitroPatch
@workflow/rollupPatch
@workflow/sveltekitPatch
@workflow/vitePatch
@workflow/vitestPatch
@workflow/world-testingPatch
@workflow/web-sharedPatch
@workflow/aiPatch
@workflow/nuxtPatch

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

CopilotAI 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

This PR extends the “friendlier errors” initiative into build-time by introducing a dedicated WorkflowBuildError (with an optional hint) in @workflow/errors and switching key @workflow/builders failure sites to throw it for more actionable build output.

Changes:

  • Add WorkflowBuildError (with hint and .is() discriminator) to @workflow/errors.
  • Update @workflow/builders to throw WorkflowBuildError for esbuild failures, unresolved built-in steps, and empty esbuild output, including user-action hints.
  • Add tests for WorkflowBuildError and publish a changeset for the patch releases.

Reviewed changes

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

FileDescription
packages/errors/src/index.tsAdds WorkflowBuildError class and documentation.
packages/errors/src/build-error.test.tsAdds vitest coverage for WorkflowBuildError behavior.
packages/builders/src/base-builder.tsReplaces generic Error throws with WorkflowBuildError + hints at key build failure sites.
.changeset/friendlier-build-errors.mdDeclares patch releases for @workflow/errors and @workflow/builders.

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

throw new WorkflowBuildError(
`${chalk.red('Failed to resolve built-in steps sources.')}\n\nCaused by: ${chalk.red(String(err))}`,
{
hint: `${chalk.yellow.bold('hint:')} run \`${chalk.cyan.italic('npm install workflow')}\` to resolve this issue.`,

CopilotAIApr 23, 2026

Copy link

Choose a reason for hiding this comment

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

options.hint is stored on the error (and appended to the message). Including a formatted hint: label + Chalk styling inside the hint field makes the hint harder to re-render in other contexts (e.g. structured UI/JSON) and can lead to double “hint:” prefixes. Consider keeping hint as plain text (no label/styling) and applying formatting at the presentation layer (or using @workflow/errors Ansi helpers if appropriate).

Suggested change
hint: `${chalk.yellow.bold('hint:')}run \`${chalk.cyan.italic('npm install workflow')}\` to resolve this issue.`,
hint: 'run `npm install workflow` to resolve this issue.',

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Fixed in efaba3ahint is now stored as plain text ('run \pnpm install workflow` to resolve this issue.') without the hint:label or chalk styling. Per the updated JSDoc onWorkflowBuildError`, the rendering layer is responsible for styling + any "hint:" label. I also stripped the chalk wrappers from the message string in the same throw so it renders cleanly in non-TTY contexts (CI logs, structured serialization).

Comment threadpackages/errors/src/index.ts Outdated
* by the workflow engine) — `WorkflowBuildError` fires during `pnpm build`,
* `next build`, or equivalent, before any workflow has started executing.
*
* Prefer attaching a short, actionable `hint` (e.g. `run \`npm install workflow\``)

CopilotAIApr 23, 2026

Copy link

Choose a reason for hiding this comment

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

The JSDoc example for hint uses npm install workflow, but other new/updated text in this PR uses pnpm install workflow. Please align this example with the recommended guidance (or switch to a package-manager-agnostic example) so docs and error hints don’t conflict.

Suggested change
*Preferattachingashort,actionable`hint`(e.g.`run \`npm install workflow\``)
*Preferattachingashort,actionable`hint`(e.g.`run \`pnpm install workflow\``)

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Fixed in efaba3a — JSDoc example now uses pnpm install workflow, matching the test and the actual call site.

Comment on lines +14 to +20
hint: 'run `pnpm install workflow` and try again',
});
expect(err.hint).toBe('run `pnpm install workflow` and try again');
expect(err.message).toMatchInlineSnapshot(`
"Build failed during steps

run \`pnpm install workflow\` and try again"

CopilotAIApr 23, 2026

Copy link

Choose a reason for hiding this comment

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

This test uses pnpm install workflow in the sample hint string, while some other new hints/docs in this PR use npm install workflow. If the intent is to be package-manager-agnostic (or to standardize on one), consider updating the test string accordingly so it doesn’t implicitly encode the chosen guidance.

Suggested change
hint: 'run `pnpm install workflow` and try again',
});
expect(err.hint).toBe('run `pnpm install workflow` and try again');
expect(err.message).toMatchInlineSnapshot(`
"Build failed during steps
run \`pnpm install workflow\` andtryagain"
hint: 'run `npm install workflow` and try again',
});
expect(err.hint).toBe('run `npm install workflow` and try again');
expect(err.message).toMatchInlineSnapshot(`
"Build failed during steps
run \`npm install workflow\` andtryagain"

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Fixed in efaba3a — all three sites (the hint in base-builder.ts, this test, and the WorkflowBuildError JSDoc example in packages/errors/src/index.ts) now use pnpm install workflow.

throw new WorkflowBuildError(
`${chalk.red('Failed to resolve built-in steps sources.')}\n\nCaused by: ${chalk.red(String(err))}`,
{
hint: `${chalk.yellow.bold('hint:')} run \`${chalk.cyan.italic('npm install workflow')}\` to resolve this issue.`,

CopilotAIApr 23, 2026

Copy link

Choose a reason for hiding this comment

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

The hint text here hard-codes npm install workflow, but elsewhere in this PR (e.g. WorkflowBuildError docs/tests) the guidance mentions pnpm install workflow. Please standardize the suggested command across the repo (or make it package-manager-agnostic, e.g. “install the workflow package”) to avoid confusing users.

Suggested change
hint: `${chalk.yellow.bold('hint:')}run \`${chalk.cyan.italic('npm install workflow')}\` to resolve this issue.`,
hint: `${chalk.yellow.bold('hint:')}install the \`${chalk.cyan.italic('workflow')}\` package to resolve this issue.`,

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Fixed in efaba3a — the hint now reads run \pnpm install workflow` to resolve this issue.` (standardized on pnpm across the hint string, the test, and the JSDoc example).

Add `WorkflowBuildError` class in `@workflow/errors` with optional `hint`
for an actionable next step, and apply it in `@workflow/builders` at
user-facing sites: failed esbuild phases, unresolved built-in steps, and
empty esbuild output now throw `WorkflowBuildError` with a hint pointing
at the likely fix. Runtime invariants remain plain `Error`.
@pranaygp

Copy link
Copy Markdown
ContributorAuthor

Superseded by #1849 — consolidated friendlier-errors PR with all 8 phases + follow-up fixes (ANSI leak, non-retry semantics, shared captureStackTrace helper).

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@pranaygp