Troubleshooting
Symptom
failed to validate annotations: annotation field "EagerLoad" is set on "Pet" schema type,but only field and edge are allowedCause
An entrest annotation is attached to a schema, field, or edge that does not support it. Each
annotation has a fixed usage location — see the summary table in
Annotation Reference.
Fix
Move the annotation to the correct Annotations() block. For example, WithEagerLoad
belongs on an edge definition inside Edges(), not on the schema root.
Symptom
spec generated no operations, thus no spec paths can be generatedCause
Every schema is skipped (WithSkip) or DefaultOperations
is empty.
Fix
Ensure at least one schema has CRUD operations enabled. An empty DefaultOperations slice fails
validation — you need at least one operation. Check for accidental WithSkip(true) on all schemas.
Symptom
no openapi type exists for type "..." of field metadataCause
Ent field type has no built-in OpenAPI mapping — common for field.JSON with custom Go types.
Fix
Add WithSchema on the field:
field.JSON("metadata", &Metadata{}).Annotations( entrest.WithSchema(ogen.String()), // or a full &ogen.Schema{})Use entrest.SchemaObjectAny for arbitrary JSON objects.
Symptom
Panic during generation:
default sort field "name" on schema "Pet" does not existCause
WithDefaultSort references a field
that is not on the schema or is not sortable.
Fix
Point WithDefaultSort at a real field name and ensure the field has
WithSortable(true) if needed.
Symptom
failed to open spec from path "../base-openapi.json": no such file or directoryor JSON decode errors.
Cause
SpecFromPath points to a file that does not
exist relative to the go:generate working directory, or the file is not valid OpenAPI JSON.
Fix
Use a path relative to the file that contains the go:generate directive. The
kitchensink example shows
the expected layout. Validate the JSON with
Recommended Tools before generation.
Symptom
Config.Spec and Config.SpecFromPath cannot be provided at the same timeFix
Choose one base spec source. Use SpecFromPath for a static JSON file; use Spec when you need Go
logic to build the base in code.
Duplicate operationId after extending the spec
Section titled “Duplicate operationId after extending the spec”Symptom
OpenAPI validation fails, or client generators report duplicate operation IDs.
Cause
A custom path in your base spec or a PostGenerateHook
defines an operationId that collides with a generated one (for example listUsers).
Fix
Rename the conflicting operationId in your base spec or override the generated ID with
WithOperationID. Run
npx ibm-openapi-validator path/to/openapi.json to catch duplicates early — see
Best Practices — Validation.
Symptom
path "/users" already exists in the specCause
Your base spec defines a path that entrest also generates. The public MergeSpec API uses strict
merging; internally entrest uses overlap merge, but component key conflicts can still surface.
Fix
Rename the custom path in your base spec (for example /users → /internal/users) or remove the
generated operation with WithExcludeOperations.
Symptom
Routes work locally but return 404 when mounted behind a prefix such as /api/v1.
Cause
BasePath does not match the mount point, or the path is stripped twice (common with stdlib handler
wrapped in an extra StripPrefix).
Fix
Set BasePath to the mount prefix
(for example /api/v1). With the stdlib handler, do not also wrap the returned handler in a
second prefix strip — entrest applies StripPrefix internally. See
Stdlib vs chi.
Symptom
GET /pets/{id} returns 400 or fails to parse the ID.
Cause
chi v5.0.12 or newer is required so path parameters populate http.Request.PathValue.
Fix
Upgrade chi: go get github.com/go-chi/chi/v5@v5.0.12 or later.
Symptom
Ent queries that worked before privacy policies now return privacy.Deny or fail silently.
Cause
Privacy policies run on every Ent call. Internal code paths (workers, seed scripts, migrations) do not pass through auth middleware, so the context lacks the identity your policies expect.
Fix
Use Ent's decision context override for trusted internal work:
ctx = privacy.DecisionContext(ctx, privacy.Allow)See Background and internal calls.
400 on create/update with unknown JSON fields
Section titled “400 on create/update with unknown JSON fields”Symptom
unknown field "extra_field"Cause
StrictMutate is enabled at
codegen time. The handler rejects request bodies with properties not defined on the schema.
Fix
Remove the extra field from the client payload, or disable StrictMutate in entc.go and
regenerate if you need to accept forward-compatible clients.
Symptom
Large POST or PATCH bodies are rejected with HTTP 413.
Cause
Default body limit is 8 MiB (MaxRequestBodyBytes).
Fix
Raise the limit in ServerConfig, or set it to -1 to disable checking (not recommended for
public APIs).
Symptom
GET /pets?filter=... returns 404 when no rows match.
Cause
ListNotFound is enabled. The
default is 200 with an empty content array.
Fix
Disable ListNotFound in entc.go if empty results should return 200, or handle 404 in your client
if you enabled it intentionally.
Enum or schema duplicated in generated client
Section titled “Enum or schema duplicated in generated client”Cause
Large specs with many filter parameters can produce verbose client code. entrest hoists enums into
components to reduce duplication, but filter-heavy schemas still generate many types.
Fix
See Keeping the spec smaller —
narrow WithFilter usage, disable
unused edge endpoints, and eager-load only edges callers need.
Generated client method names are unstable
Section titled “Generated client method names are unstable”Cause
Default operationId values follow a predictable pattern (createUser, listUserPets), but
hand-editing openapi.json or conflicting base-spec IDs can break stability.
Fix
Set explicit IDs with WithOperationID
on schemas or edges that feed your client generator.
- Compare your setup to the simple example or kitchensink example.
- Validate your spec with tools listed in Recommended Tools.
- Open an issue on GitHub with the codegen error,
relevant schema snippets, and your
entc.goconfig.

