Skip to content

fix: a repo without the model's issue type gets one issue, not two - #4

Open
tonyandrewmeyer wants to merge 3 commits into
canonical:mainfrom
tonyandrewmeyer:fix-issue-type-duplicate
Open

fix: a repo without the model's issue type gets one issue, not two#4
tonyandrewmeyer wants to merge 3 commits into
canonical:mainfrom
tonyandrewmeyer:fix-issue-type-duplicate

Conversation

@tonyandrewmeyer

Copy link
Copy Markdown
Collaborator

gh issue create --type <t> creates the issue and only then fails on the type, so the retry-without---type that followed a failure created a second, identical issue: same title, same body, same run marker. A fork, or any repo whose organisation has not enabled issue types, got two issues for every enrichment that asked for one.

Issue types are now looked up and matched before the create, the same way labels already were, so there is nothing left to retry. The match ignores case and passes the repo's own spelling, since the model is asked for "bug" and GitHub's type is "Bug" - which means the retry was reachable even where types do exist, and I think this would have started duplicating on canonical/operator as soon as a failure was classified as a defect.

A type the repo doesn't have is dropped with a note in the step summary, which is what already happens to a label it doesn't have.

Found by running the notifier end to end against a deliberately-failing workflow in my fork, which has no issue types at all: tonyandrewmeyer/operator#43 and #44 are the pair it produced.

`gh issue create --type <t>` creates the issue and only then fails on the
type, so the retry-without-`--type` that followed a failure created a second,
identical issue: same title, same body, same run marker. A fork, or any repo
whose organisation has not enabled issue types, hit this on every enrichment
that asked for one.

Issue types are now resolved before the create, the same way labels already
were, and there is nothing left to retry. The match ignores case and passes
the repo's own spelling, because the model is asked for "bug" and GitHub's
type is "Bug" - so the failure path was reachable even where types do exist.
A type the repo doesn't have is dropped with a note in the step summary,
which is what happens to an unknown label.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013trjz242SkZ2SxPami6XE7
tonyandrewmeyer and others added 2 commits September 11, 2026 09:27
Issues are written `#44` everywhere a person sees one, and the model returns
that string often enough to matter. The schema wants an integer, so the whole
envelope was rejected and a usable enrichment was thrown away over a `#`,
falling back to the plain notice. Seen on a real run, against a candidate the
notifier itself had just passed down.

A `#`-prefixed or bare digit string is now read as the number it means, in the
envelope and in each `also` entry. Anything else is left exactly as it is, for
the schema to reject on its own terms.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013trjz242SkZ2SxPami6XE7
`str(HTTPError)` is only ever "HTTP Error 400: Bad Request", which doesn't say
whether the model, the key or the schema was the problem. OpenRouter puts the
reason in the response body, so a 400 cost a schema read to diagnose when the
answer was one line away.

The body is now read and appended to the message, JSON `error.message` where
there is one and the raw text otherwise, truncated. Reading it is not allowed
to raise: an unreadable explanation must not lose the status code that came
with it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SEuiHk71P4R7hZD7dqfvGh
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.

1 participant