Skip to content

check:generated fails on dev: HttpApiError.BadRequest produces invalid TS identifier #246

Description

@alltomatos

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)

  1. 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.
  2. 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.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions