Repository navigation
Description
What happened
After fixing #245 (ScheduleValidationError missing its literal discriminator), bun run check:generated gets further but still fails, now with:
error: Failed to format types.ts: SyntaxError: '=' expected. (11:19)
9 | export const isInvalidRequestError = (value: unknown): value is InvalidRequestError => typeof value === "object" && value !== null && "_tag" in value && value["_tag"] === "InvalidRequestError"
10 |
> 11 | export type effect/HttpApiError/BadRequest = { readonly "_tag": "BadRequest"; }
| ^
12 | export const iseffect/HttpApiError/BadRequest = (value: unknown): value is effect/HttpApiError/BadRequest => typeof value === "object" && value !== null && "_tag" in value && value["_tag"] === "BadRequest"
Reproduced locally on a clean dev checkout (with #245's fix applied on top, using [email protected] as pinned in root package.json) — this is not caused by any PR, it's the next layer of a chain of masked failures (formatMinutes locale → ScheduleValidationError discriminator → this).
Root cause
packages/protocol/src/groups/system.ts's system.update endpoint declares error: [HttpApiError.BadRequest], using effect's built-in HttpApiError.BadRequest class directly instead of a repo-defined error class. packages/httpapi-codegen/src/index.ts's declaredErrorFields() resolves this class's identifier via SchemaAST.resolveIdentifier(schema.ast), which for this built-in class returns the internal module-qualified name effect/HttpApiError/BadRequest (slashes included) instead of falling back to the literal tag ("BadRequest"). That string is then emitted as a TypeScript type name, which is invalid syntax.
system.update (packages/server/src/handlers/system.ts:11, yield* new HttpApiError.BadRequest()) is the only place in the codebase using HttpApiError.BadRequest directly — every other endpoint uses a repo-defined error class with an explicit name/_tag literal (see #245).
Possible fixes (needs a decision, not attempting in this issue)
- Narrow fix, follows existing precedent: replace
HttpApiError.BadRequestinsystem.tswith a repo-defined error class (e.g.SystemUpdateError) carrying its ownnameliteral, matching theScheduleValidationError/ProjectCopyErrorpattern. Smallest change, no risk tohttpapi-codegenitself. - General fix: make
declaredErrorFields()inpackages/httpapi-codegen/src/index.tsfall back totag.literalwhenSchemaAST.resolveIdentifier()returns a string that isn't a valid TS identifier (e.g. contains/), instead of trusting it unconditionally. Fixes this for any future use of a built-inHttpApiError.*class, but touches shared codegen logic.
Filing as a separate issue rather than folding into #245 since it's a distinct root cause in a different file.
Activity
alltomatos commentedon Sep 15, 2026
Fixed in commit 60ec4c3 and types regenerated in commit 6d262e1 by declaring SystemUpdateError schema class instead of using raw HttpApiError.BadRequest.