Skip to content

fix(routines): make routine and day creation work against wger 2.7 - #4

Merged
rolandgeider merged 1 commit into
wger-project:masterfrom
wromansky:fix/routine-writes-wger-27
Aug 13, 2026
Merged

fix(routines): make routine and day creation work against wger 2.7#4
rolandgeider merged 1 commit into
wger-project:masterfrom
wromansky:fix/routine-writes-wger-27

Conversation

@wromansky

Copy link
Copy Markdown
Contributor

Two defects that make the core write path fail. Both surfaced by pointing this server at a wger 2.7.0a2 instance and asking an assistant to build a six-day routine: it created the routine only after a retry, then failed to add a single day, seven times over.

1. add_routine_day can never succeed with its defaults

day_type defaults to "standard", which is not one of wger's DayType choices — those are custom, enom, amrap, hiit, tabata, edt, rft, afap. Every default call posts an invalid type:

POST /api/v2/day/  ->  400
{"type": ["\"standard\" is not a valid choice."]}

Confirmed three ways: the endpoint's OPTIONS schema, wger/manager/models/day.py, and replaying the tool's exact payload by hand.

The default is now custom. An unrecognised value is refused locally with the valid list, instead of spending a round trip on an error the caller then has to parse.

2. create_routine omits a required field

end is required=True on POST /routine/, but it was only sent when the caller supplied one — so the tool's own documented "Start defaults to today" path is a guaranteed 400.

end now defaults to start + 12 weeks, and an end at or before start is refused up front. A caller who cares still passes it explicitly.

Why this is worse for an LLM caller than it looks

The 400 body is not always surfaced to the model, so it retries the same call with different arguments and gets identical results. The agent that hit this tripped its own loop-detection circuit breaker after seven attempts and aborted the turn, having written a routine with zero days. From the user's side it looks like the model failing; the tool was simply broken.

Tests

6 new tests in tests/test_routine_writes.py: end is always sent, an explicit end is preserved, end <= start is refused, the default day type is one wger accepts, every declared type is passed through, and an unknown type is refused with the options named.

Full suite passes (77) and ruff check is clean.

Also verified against a live instance rather than mocks alone: the payload the fixed tool now sends returns 201 Created.

Note

Independent of #2 and #3 — off master, and it touches only create_routine / add_routine_day.

Two defects that make the core write path fail. Both were found by pointing
this server at a wger 2.7.0a2 instance and asking an assistant to build a
six-day routine: it created the routine only after a retry, then failed to
add a single day, seven times over.

**add_routine_day can never succeed with its defaults.** day_type defaults to
"standard", which is not one of wger's DayType choices (custom, enom, amrap,
hiit, tabata, edt, rft, afap). Every call posts an invalid type and wger
answers 400 with {"type": ["\"standard\" is not a valid choice."]}. The
default is now "custom", and an unrecognised value is refused locally with the
valid list, rather than spending a round trip on an error the caller then has
to parse.

**create_routine omits a required field.** end is required on POST /routine/,
but it was only sent when the caller supplied one, so the documented "start
defaults to today" path is a 400. end now defaults to start + 12 weeks, and
an end at or before start is refused up front.

An LLM caller makes this worse than it looks: the 400 body is not always
surfaced to the model, so it retries the same call with different arguments
and identical results. The agent that hit this tripped its own loop detector
after seven attempts.

Adds 6 tests: end is always sent, an explicit end is preserved, end <= start
is refused, the default day type is one wger accepts, every declared type is
passed through, and an unknown type is refused with the options named.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@rolandgeider

Copy link
Copy Markdown
Member

thanks for the pr! I actually had this on my TODO list as I had ran into this as well. To avoid these errors from happening, we'll use the api python client generated directly from the openAPI spec

@rolandgeider
rolandgeider merged commit 5a09d99 into wger-project:master Aug 13, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants