Summary
Two doc gaps that cost several hours of debugging each, encountered while building a service package with multiple UseCaseService subclasses. Filing as one doc issue since both are troubleshooting-adjacent and likely belong in the same getting-started / FAQ section.
Doc gap A: URL path naming convention for UseCaseService subclasses
Observation
A service class named ChecklistItemService is exposed at:
/api/checklist_item_service/<method_name>
Not (as one might expect from snake_case conversion of camelCase):
/api/check_list_item_service/<method_name> ❌
The class name is lowercased as a single token; camelCase boundaries are not split on underscores.
Why this is confusing
- Developers writing curl tests / SDK wrappers / reverse-proxy routes by hand will guess wrong paths and get 404.
- It's not obvious from any doc page what rule is applied (the path appears correct in
openapi.json after the fact, but you have to know to look there).
- Different RPC frameworks use different conventions (FastAPI's own router uses snake_case-with-splits for class-based view names; gRPC uses fully-qualified names; etc.) — picking one explicitly and documenting it removes the guesswork.
Suggested doc location
references/lpk-builder.md (if it covers nexusx service URL layout) or a dedicated "Service URL Convention" section in the main README / getting-started. Something like:
URL convention. Each UseCaseService subclass is exposed at /api/<lowercase_class_name>/<method_name>. The class name is lowercased as a single token; camelCase boundaries are preserved (e.g., ChecklistItemService → /api/checklist_item_service/, not /api/check_list_item_service/).
Doc gap B: Pydantic v2 forbids setattr of undeclared fields on SQLModel instances
Observation
When trying to attach runtime-computed data to a SQLModel instance (e.g., pre-fetched M:N associations, see related issue #108):
parent.targets = pre_loaded_list # ❌ ValueError
Pydantic v2 raises:
ValueError: "Parent" object has no field "targets"
This is a Pydantic v2 + SQLModel interaction (not a nexusx bug per se), but it bites anyone following the natural "load related data, attach to model, model_validate" pattern that earlier Pydantic v1 / SQLAlchemy examples often used.
Suggested doc location
A troubleshooting / FAQ entry:
"X object has no field Y" when attaching runtime data to a model instance.
Pydantic v2 enforces strict schema on SQLModel instances: only fields declared on the model can be set via =. To pass runtime-computed data into a DTO, do the attachment on the DTO after model_validate, not on the model instance:
# ❌ Fails under Pydantic v2:
parent.targets = some_list
dto = ParentDTO.model_validate(parent)
# ✅ Works:
dto = ParentDTO.model_validate(parent)
dto.targets = [TargetDTO.model_validate(t) for t in some_list]
Alternatively, declare targets as a real relationship field on the model (then lazy="noload" + manual load + setattr works because Pydantic sees it as a declared field).
Why this is worth documenting
Related
Both of those issues benefit from clearer docs on the model → DTO lifecycle.
Summary
Two doc gaps that cost several hours of debugging each, encountered while building a service package with multiple
UseCaseServicesubclasses. Filing as one doc issue since both are troubleshooting-adjacent and likely belong in the same getting-started / FAQ section.Doc gap A: URL path naming convention for
UseCaseServicesubclassesObservation
A service class named
ChecklistItemServiceis exposed at:Not (as one might expect from snake_case conversion of camelCase):
The class name is lowercased as a single token; camelCase boundaries are not split on underscores.
Why this is confusing
openapi.jsonafter the fact, but you have to know to look there).Suggested doc location
references/lpk-builder.md(if it covers nexusx service URL layout) or a dedicated "Service URL Convention" section in the main README / getting-started. Something like:Doc gap B: Pydantic v2 forbids setattr of undeclared fields on SQLModel instances
Observation
When trying to attach runtime-computed data to a SQLModel instance (e.g., pre-fetched M:N associations, see related issue #108):
Pydantic v2 raises:
This is a Pydantic v2 + SQLModel interaction (not a nexusx bug per se), but it bites anyone following the natural "load related data, attach to model, model_validate" pattern that earlier Pydantic v1 / SQLAlchemy examples often used.
Suggested doc location
A troubleshooting / FAQ entry:
Why this is worth documenting
Related
Both of those issues benefit from clearer docs on the model → DTO lifecycle.