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 bun@1.3.14 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.BadRequest in system.ts with a repo-defined error class (e.g. SystemUpdateError) carrying its own name literal, matching the ScheduleValidationError/ProjectCopyError pattern. Smallest change, no risk to httpapi-codegen itself.
- General fix: make
declaredErrorFields() in packages/httpapi-codegen/src/index.ts fall back to tag.literal when SchemaAST.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-in HttpApiError.* 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.
What happened
After fixing #245 (
ScheduleValidationErrormissing its literal discriminator),bun run check:generatedgets further but still fails, now with:Reproduced locally on a clean
devcheckout (with #245's fix applied on top, usingbun@1.3.14as pinned in rootpackage.json) — this is not caused by any PR, it's the next layer of a chain of masked failures (formatMinuteslocale →ScheduleValidationErrordiscriminator → this).Root cause
packages/protocol/src/groups/system.ts'ssystem.updateendpoint declareserror: [HttpApiError.BadRequest], usingeffect's built-inHttpApiError.BadRequestclass directly instead of a repo-defined error class.packages/httpapi-codegen/src/index.ts'sdeclaredErrorFields()resolves this class's identifier viaSchemaAST.resolveIdentifier(schema.ast), which for this built-in class returns the internal module-qualified nameeffect/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 usingHttpApiError.BadRequestdirectly — every other endpoint uses a repo-defined error class with an explicitname/_tagliteral (see #245).Possible fixes (needs a decision, not attempting in this issue)
HttpApiError.BadRequestinsystem.tswith a repo-defined error class (e.g.SystemUpdateError) carrying its ownnameliteral, matching theScheduleValidationError/ProjectCopyErrorpattern. Smallest change, no risk tohttpapi-codegenitself.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.