fix: make failed-post retry work — enum status mismatch - #33
Merged
Conversation
Ooscaar
force-pushed
the
fix/failed-post-retry-enum-mismatch
branch
from
July 31, 2026 09:05
9300612 to
2d99db3
Compare
Ooscaar
force-pushed
the
fix/failed-post-retry-enum-mismatch
branch
3 times, most recently
from
July 31, 2026 14:18
d8cf278 to
84d680d
Compare
…e-plugin#1)
The MCP retry path never recognized a failed post. Two bugs conspired:
1. posts_retry compared the post's status — a generated plain Enum with an
unstable positional name (Status10 in the released build, renumbered on
every spec regen) — against the handwritten PostStatus str-enum. Two
different enum classes never compare equal, so every failed post was
rejected with 'is not in failed status (current: Status10.FAILED)'.
2. posts_retry_all_failed / posts_list_failed passed PostStatus.FAILED into
the query string, where httpx serialized it via str() as
'status=PostStatus.FAILED' instead of 'status=failed', so the API
matched nothing and the tools reported no failed posts.
Fixes:
- codegen: add --use-subclass-enum so generated enums are (str, Enum) and
compare equal to their plain value and to the PostStatus twin
(models regenerated).
- resources: unwrap Enum members to .value in _build_params/_build_payload —
in the generator template (each generated resource carries its own copy
that shadows BaseResource) and in the handwritten BaseResource
(resources regenerated).
- mcp: posts_retry guard compares plain status values and reports the clean
value ('current: scheduled') in the warning.
- tests: unit tests pin enum unwrapping and value-compatibility;
test_mcp_retry_regression.py drives the real MCP tools against a strict
in-memory fake API (httpx.MockTransport, no network) that only matches
the literal status=failed — both bugs reproduce exactly against the
unfixed code with the same error messages as the issue.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Ooscaar
force-pushed
the
fix/failed-post-retry-enum-mismatch
branch
from
July 31, 2026 14:28
84d680d to
33632d9
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes zernio-dev/zernio-claude-plugin#1: the MCP retry path never recognized a failed post, so there was no working way to retry one — users had to delete and recreate.
Two bugs conspired:
posts_retryguard never matched. The post's status deserializes into a codegen'd plainEnumwith an unstable positional name (Status10in the released build, renumbered on every spec regen), while the guard compared against the handwrittenPostStatusstr-enum. Two different enum classes never compare equal in Python, so every failed post was rejected withis not in failed status (current: Status10.FAILED).posts_retry_all_failed/posts_list_failedqueried with a mangled filter.PostStatus.FAILEDwas passed through to httpx, which serializes params viastr()— sendingstatus=PostStatus.FAILEDinstead ofstatus=failed. The API matched nothing, so the tools reported "No failed posts to retry".Changes
Single commit on top of
develop(branch was rebuilt and squashed; the OAuth discovery work previously on this branch is already indevelopas d88b72c):--use-subclass-enumtogenerate_models.py— generated enums are now(str, Enum), so members compare equal to their plain value and to thePostStatustwin (models regenerated; mixin-only diff, no renames).Enummembers to.valuein_build_params/_build_payload— in the generator template (each generated resource carries its own shadowing copy) and in the handwrittenBaseResource. Fixes every enum filter SDK-wide, e.g. the documentedclient.posts.list(status=PostStatus.FAILED).posts_retrycompares plain status values and reports the clean value (current: scheduled) in the warning — robust even if codegen flags change.test_mcp_retry_regression.pydrives the real MCP tools against a strict in-memory fake API (httpx.MockTransport, no network) that only matches the literalstatus=failed.Testing
is not in failed status (current: Status7.FAILED)/No failed posts to retry.) and pass with the fix; one test assertsstatus=failedis literally on the wire. ✅Consumer impact
No breaking changes. Enum-filtered list calls that silently returned wrong results now return correct ones,
post.status == "failed"now behaves intuitively, and.valueaccess is unchanged.Follow-up (out of scope)
Root-cause cleanup in the API repo: name the post status as
components/schemas/PostStatusin the OpenAPI spec so codegen stops emitting unstableStatusNnames and the handwritten twin enum can be retired.🤖 Generated with Claude Code