Troubleshooting the TypeScript Client
Search this page for the message you see.
Installing
| Message | Cause | Fix |
|---|---|---|
unmet peer @ahoo-wang/wow-client@~x.y.z: found … | The Wow packages of the application are on different minor versions | Install one version of every Wow package (Compatibility and Versions) |
Cannot find module 'react/compiler-runtime' | React older than 19 | wow-react and the view engine need React 19 or later |
pnpm add installs 9.x | latest names the newest stable release; a Wow 10 pre-release is on its own dist-tag | Install the version of your services, or the pre-release's dist-tag (Release status) |
Compiling
| Message | Cause | Fix |
|---|---|---|
TS2345 on a filter field, such as 'status' or 'state.statsu' | A query client types its fields: the system fields and the generated <Aggregate>StateField. A state field lives under state. | Name it state.status; regenerate if the service changed |
TS2322: Type 'number' is not assignable to type 'string' on an amount or an id | A Long, BigInteger or BigDecimal field is a string, read and written exactly | Pass its digits as text: unitPrice: '19.90' (Exact numbers) |
TS2339: Property '…' does not exist on a query's record | The query's projection.include left that path out, and the result is narrowed to what it includes | Include the path, or drop the projection |
TS2307: Cannot find module './generated' under NodeNext | Node resolution needs the file | Import ./generated/index.js |
TS2882: Cannot find module or type declarations for side-effect import of '…/styles.css' | TypeScript 6 checks side-effect imports | A Vite project declares *.css through vite/client; elsewhere add declare module '*.css'; |
Sending requests
| Message | Cause | Fix |
|---|---|---|
Failed to parse URL from /eshop-ordering/… | The client has no fetcher, and the default Fetcher has no base URL | Create the clients with { fetcher } (Send Commands) |
404 with an about:blank problem | The route does not exist where the request went: a gateway that does not route the context's prefix, or a basePath it does not expect | Send to the service or the gateway that serves /<context>/… |
TypeError: The path … needs id. | A command on an existing aggregate was sent with an empty id | Pass the aggregate's id |
TypeError: Failed to fetch in a browser, a CORS message in the console | The service does not allow the page's origin | Configure CORS on the service or the gateway, or serve the API from the page's origin |
401 wow.auth.unauthenticated on every request | No token, or the token is not sent by the Fetcher the clients use | Apply CoSec to that Fetcher and sign in (Authentication) |
Service answers
A refusal rejects with a WowProblemError; its code is one of these, or a domain code of the generated <Context>ErrorCodes. Error Codes lists them all.
code | Status | Cause | Fix |
|---|---|---|---|
A domain code, <context>.<aggregate>.<name> | 422 unless the service says otherwise | The aggregate rejected the command | Show problem.detail; the request itself has to change |
wow.command.invalid | 400 | The command failed validation | Show each of violations beside its path |
wow.aggregate.not-found | 404 | No aggregate with that id | Handle the absence |
wow.aggregate.version-mismatch | 409, or 412 with expectedVersion | Another write came first | Read the state again and decide again |
wow.command.request-id-reused | 409 | A request id was used by another command | Generate a new request id for a new command |
wow.wait.timeout | 504 | The wait ran out of time; the command may have committed | Retry with the same request id, or read the state |
wow.wait.invalid | 400 | The wait plan is not a chain the service can follow | Build the plan from the generated hops of each context |
wow.query.invalid | 400 | The query broke a rule of the query model | Read each violation's code and path |
wow.query.min-version-not-reached | 409 | A read's minVersion was not reached within the wait | Retry after retry.afterMs; the problem's version is the current one |
wow.command.busy, wow.query.busy | 429 | The aggregate, the node or the store is busy | Retry after retry.afterMs |
wow.node.standby | 503 | The service is on standby before a migration's cut-over and serves reads only | Retry later |
error.retry says whether a retry can succeed and whether to keep the request id.
Streams
| Symptom | Cause | Fix |
|---|---|---|
| A command stream ends before the last hop of its plan | A saga on the way sent nothing further: the last result has chainEnded, and pending lists the hops that will not come | Treat it as the chain's end, as the eShop's checkout does when a payment is declined |
A command stream's last result is not SUCCEEDED | The command, or a command the chain led to, was rejected or failed after admission | Read the result's status and error |
A query stream errors with a WowProblemError | The service failed midway with a problem the client cannot resume past | Handle it like a failed request |
| The connection stays open after the component is gone | The stream was never read to its end or cancelled | Pass a signal and abort it on cleanup, or cancel the reader |
Generating
| Exit code or message | Cause | Fix |
|---|---|---|
| Exit 2 | The input cannot be read or fetched, is neither a Manifest nor an OpenAPI 3 document, or an option is wrong | Read the message; an http(s) input that needs credentials takes -H 'Authorization: Bearer …' |
| Exit 3 | The configuration cannot be read, parsed or validated | Fix the file the message names (configuration) |
| Exit 4 | The document cannot be generated, or --strict and the run logged a warning | Read the warnings of the run |
| Exit 5 | The output cannot be written, a path escapes it, or a newer generator wrote its .wow-generator.json | Generate with the generator of the version that wrote it |
| The committed clients differ from a new run | The Manifest baseline changed, or the generator's version did | Commit the new output with the change that caused it |
Run with --verbose for every step and the stack trace of a failure.
Still stuck
Collect the failing request's method and URL, the status, the problem's body and its Wow-Request-Id, the package versions (pnpm ls @ahoo-wang/wow-client @ahoo-wang/fetcher) and the service's Wow version, and open an issue at Ahoo-Wang/Wow.