feat: export semantic error types and add API reference docs#1447
feat: export semantic error types and add API reference docs#1447
Conversation
🦋 Changeset detectedLatest commit: 380b624 The changes in this PR will be included in the next version bump. This PR includes changesets to release 20 packages
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 |
There was a problem hiding this comment.
Pull request overview
This PR expands the public surface area and documentation around semantic error types by re-exporting them via workflow/internal/errors, adding/standardizing world-level error classes in @workflow/errors, and introducing API reference docs for these errors. It also adds DEBUG-gated request timing logs in the Vercel world client and fixes a CLI env var passthrough.
Changes:
- Re-export semantic error types from
workflow/internal/errorsand add new world-level semantic error classes to@workflow/errors. - Add/standardize TSDoc on error classes and add API reference docs pages for the error types.
- Add DEBUG-gated HTTP timing logs in
@workflow/world-verceland passWORKFLOW_LOCAL_BASE_URLthrough CLI inspect env.
Reviewed changes
Copilot reviewed 18 out of 18 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/world-vercel/src/utils.ts | Adds lightweight DEBUG-gated HTTP timing logging around fetch() requests. |
| packages/workflow/src/internal/errors.ts | Re-exports semantic/world error types from @workflow/errors via workflow/internal/errors. |
| packages/errors/src/index.ts | Adds/extends semantic error classes (world-level) and improves TSDoc consistency/examples. |
| packages/core/src/runtime/helpers.ts | Adds runtime debug logs for event pagination load timing during replay. |
| packages/cli/src/lib/inspect/env.ts | Includes WORKFLOW_LOCAL_BASE_URL in env var collection for inspect/health checks. |
| docs/content/docs/api-reference/workflow/workflow-world-error.mdx | New API reference page for WorkflowWorldError. |
| docs/content/docs/api-reference/workflow/workflow-run-not-found-error.mdx | New API reference page for WorkflowRunNotFoundError. |
| docs/content/docs/api-reference/workflow/workflow-run-failed-error.mdx | New API reference page for WorkflowRunFailedError. |
| docs/content/docs/api-reference/workflow/workflow-run-cancelled-error.mdx | New API reference page for WorkflowRunCancelledError. |
| docs/content/docs/api-reference/workflow/too-early-error.mdx | New API reference page for TooEarlyError. |
| docs/content/docs/api-reference/workflow/throttle-error.mdx | New API reference page for ThrottleError. |
| docs/content/docs/api-reference/workflow/run-expired-error.mdx | New API reference page for RunExpiredError. |
| docs/content/docs/api-reference/workflow/hook-not-found-error.mdx | New API reference page for HookNotFoundError. |
| docs/content/docs/api-reference/workflow/entity-conflict-error.mdx | New API reference page for EntityConflictError. |
| docs/content/docs/api-reference/workflow/meta.json | Adds new error reference pages to the workflow API reference sidebar. |
| .changeset/error-docs-and-exports.md | Changeset for workflow + @workflow/errors export/doc updates. |
| .changeset/early-bats-make.md | Changeset for @workflow/world-vercel DEBUG HTTP timing logs. |
| .changeset/bumpy-mice-do.md | Changeset for @workflow/cli env var passthrough fix. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
packages/world-vercel/src/utils.ts
Outdated
|
|
||
| /** | ||
| * Lightweight debug logger for HTTP requests. Activated when the DEBUG | ||
| * env var includes "workflow:" (matching the standard `debug` module | ||
| * convention used by @workflow/core). | ||
| */ | ||
| const HTTP_DEBUG_ENABLED = | ||
| typeof process !== 'undefined' && | ||
| typeof process.env.DEBUG === 'string' && | ||
| (process.env.DEBUG.includes('workflow:') || process.env.DEBUG === '*'); | ||
|
|
||
| function httpLog( | ||
| method: string, | ||
| endpoint: string, | ||
| status: number, | ||
| ms: number | ||
| ): void { | ||
| if (HTTP_DEBUG_ENABLED) { | ||
| console.debug( | ||
| `[workflow:world-vercel:http] ${method} ${endpoint} -> ${status} (${ms}ms)` | ||
| ); | ||
| } | ||
| } | ||
| import { | ||
| ErrorType, | ||
| getSpanKind, |
| /** | ||
| * Lightweight debug logger for HTTP requests. Activated when the DEBUG | ||
| * env var includes "workflow:" (matching the standard `debug` module | ||
| * convention used by @workflow/core). | ||
| */ | ||
| const HTTP_DEBUG_ENABLED = | ||
| typeof process !== 'undefined' && | ||
| typeof process.env.DEBUG === 'string' && | ||
| (process.env.DEBUG.includes('workflow:') || process.env.DEBUG === '*'); |
a480112 to
cfdd0d6
Compare
📊 Benchmark Results
workflow with no steps💻 Local Development
workflow with 1 step💻 Local Development
workflow with 10 sequential steps💻 Local Development
workflow with 25 sequential steps💻 Local Development
workflow with 50 sequential steps💻 Local Development
Promise.all with 10 concurrent steps💻 Local Development
Promise.all with 25 concurrent steps💻 Local Development
Promise.all with 50 concurrent steps💻 Local Development
Promise.race with 10 concurrent steps💻 Local Development
Promise.race with 25 concurrent steps💻 Local Development
Promise.race with 50 concurrent steps💻 Local Development
workflow with 10 sequential data payload steps (10KB)💻 Local Development
workflow with 25 sequential data payload steps (10KB)💻 Local Development
workflow with 50 sequential data payload steps (10KB)💻 Local Development
workflow with 10 concurrent data payload steps (10KB)💻 Local Development
workflow with 25 concurrent data payload steps (10KB)💻 Local Development
workflow with 50 concurrent data payload steps (10KB)💻 Local Development
Stream Benchmarks (includes TTFB metrics)workflow with stream💻 Local Development
stream pipeline with 5 transform steps (1MB)💻 Local Development
10 parallel streams (1MB each)💻 Local Development
fan-out fan-in 10 streams (1MB each)💻 Local Development
SummaryFastest Framework by WorldWinner determined by most benchmark wins
Fastest World by FrameworkWinner determined by most benchmark wins
Column Definitions
Worlds:
❌ Some benchmark jobs failed:
Check the workflow run for details. |
🧪 E2E Test Results❌ Some tests failed Summary
❌ Failed Tests▲ Vercel Production (2 failed)nitro (1 failed):
nuxt (1 failed):
🌍 Community Worlds (58 failed)mongodb (3 failed):
redis (2 failed):
turso (53 failed):
Details by Category❌ ▲ Vercel Production
✅ 💻 Local Development
✅ 📦 Local Production
✅ 🐘 Local Postgres
✅ 🪟 Windows
❌ 🌍 Community Worlds
✅ 📋 Other
❌ Some E2E test jobs failed:
Check the workflow run for details. |
- Resolve merge conflict with HookConflictError from main - Fix class hierarchy: EntityConflictError, RunExpiredError, TooEarlyError, ThrottleError now extend WorkflowWorldError (not WorkflowError) - Move telemetry import to top of utils.ts with other imports - Rename TooEarlyError.retryAfter to retryAfterDate to avoid type conflict with WorkflowWorldError.retryAfter (number vs Date) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Resolve merge conflict in world-vercel/utils.ts - Add @skip-typecheck markers to all error API reference docs code samples that use placeholder variables (world, runId, run, etc.) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
| // Return timeout to queue so it retries later | ||
| if (TooEarlyError.is(err)) { | ||
| const retryAfter = err.retryAfter ?? new Date(Date.now() + 1000); | ||
| const retryAfter = err.retryAfterDate ?? new Date(Date.now() + 1000); |
There was a problem hiding this comment.
is this real? does this mean that before this PR the retryAfter was not actually working? or did this PR change the type so that it's now correct?
There was a problem hiding this comment.
This was introduced by this PR — not a pre-existing bug. On main, TooEarlyError extends WorkflowError (which has no retryAfter property), so the retryAfter?: Date property worked fine.
This PR changes the class hierarchy so TooEarlyError extends WorkflowWorldError, which already has retryAfter?: number (seconds, from HTTP Retry-After header). TypeScript doesn't allow a subclass to narrow a property from number to Date, so I renamed the TooEarlyError property to retryAfterDate to avoid the clash. The semantics are the same — just the property name changed.
|
|
||
| {/* @skip-typecheck: incomplete snippet with placeholder variables */} | ||
| ```typescript lineNumbers | ||
| import { ThrottleError } from "workflow/internal/errors" |
There was a problem hiding this comment.
use should not import from workflow/internal. it should be workflow/errors directly
… section - Replace @skip-typecheck with proper `declare` + `// @setup` lines so code samples are typechecked but setup lines hidden from readers - Add `workflow/errors` export to package.json (public API, replaces `workflow/internal/errors` in docs) - Add `workflow/errors` path mapping in docs-typecheck type-checker - Add HookConflictError to re-export list - Move all error docs under api-reference/workflow/errors/ subdirectory - Update all internal cross-references and links Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Move semantic error docs to api-reference/workflow-errors/ (matching the workflow/errors import path, like workflow-api for workflow/api) - Keep FatalError and RetryableError in api-reference/workflow/ since they're imported from workflow, not workflow/errors - Fix all cross-reference links Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Summary
HookNotFoundError,EntityConflictError,RunExpiredError,TooEarlyError,ThrottleError,RunNotSupportedError,WorkflowWorldError) fromworkflow/internal/errors@workflow/errors:WorkflowWorldError,EntityConflictError,RunExpiredError,TooEarlyError,ThrottleError(world-level semantic errors).is()method, key properties)Test plan
pnpm buildpassespnpm typecheckpassesworkflow/internal/errorsexports are accessible at runtime🤖 Generated with Claude Code