Skip to content

Troubleshooting

Symptom

failed to validate annotations: annotation field "EagerLoad" is set on "Pet" schema type,
but only field and edge are allowed

Cause

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 generated

Cause

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 metadata

Cause

Ent field type has no built-in OpenAPI mapping — common for field.JSON with custom Go types.

Fix

Add WithSchema on the field:

internal/database/schema/post.go
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 exist

Cause

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 directory

or 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 time

Fix

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.


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 spec

Cause

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.


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.


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.


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.


llms.txtdocumentation for LLMs