Skip to content

Build1 publisher3 min readPublished

The agent said the Jira move failed. It had already committed the write.

A step-limit abort was reported as a task failure after the transition had gone through. The harness described its own loop, not the system of record, and a retry was one keystroke away.

The Engineer · Build desk

Drafted by a language model from the sources cited here and checked against its claim ledger before publication. How we use AISend a correction

Illustration accompanying The agent said the Jira move failed. It had already committed the write.
Generated illustration

What happened

  • The author asked an agent to move a ticket to In Progress and it returned an error saying too many steps, task aborted.
  • Out of habit rather than suspicion, the author opened Jira before sending a follow-up prompt and found the ticket already sitting in In Progress.
  • The task was to take issue KAN-1 from To Do to In Progress.
  • The author was already composing a follow-up prompt of the okay, let's try that again, this time do X kind when he checked Jira.
  • The agent had spent eleven visible turns wrestling with an API before returning the error.

Compiled by The EngineerSomething wrong?How this is made

Why it matters

An agent asked to move Jira issue KAN-1 from To Do to In Progress returned an error - too many steps, task aborted - and the developer running it, writing on dev.to, opened the board out of habit before replying and found the ticket already sitting in In Progress [1][2][3]. The defect worth naming is not dishonesty in the model; it is a harness that reported the state of its own control loop as the state of the world, after the world had already changed [10][16].

The author says he read the three logs the agent keeps of its own operation: an audit trail of every tool call and its raw response, a debug log underneath, and a conversation log of what the model reasoned at each step, all timestamped rather than narrated after the fact [6]. The sequence in those logs is unremarkable up to the end. The agent read the issue, then asked Jira which transitions were available from the current status; both were clean, successful reads [7]. It then fired the transition and got it wrong, passing the transition ID as a number where the API wanted a string, corrected itself, and sent the ID as a string on the next call, which went through [8]. Twenty-one characters came back, the shape of a real Jira success response rather than an error body, and the ticket moved [9].

Then the step limit fired [10]. That limit exists for a good reason: an agent calling tools in a loop needs a ceiling on turns, or a confused model spins forever, burning time and API calls on a task that was never going to converge [11]. By that point the run had spent eleven visible turns wrestling with the API [5], which is what made the abort message credible. The problem is the abort was raised as a task-level failure with no reconciliation against the writes the run had already committed, and the last write was a successful one [16].

The consequence is the retry. The author was composing the usual follow-up - okay, let's try that again, this time do X - when he checked [4]. Send that, and the second attempt is issued against a ticket whose status has already changed [17]. For a status transition the damage is small and visible. For anything that creates, pays, notifies, or merges, the same failure shape produces a duplicate, and the operator authorises it while reading a message that says nothing happened.

Worth noting how the run got long enough to hit the ceiling. This was live-testing work on six integrations built in an earlier session and marked NOT YET LIVE-TESTED: Jira, Linear, Slack, Figma, Sentry and Postgres [12]. Before a single ticket moved, three real obstacles: Atlassian now issues classic and scoped API tokens and the integration protocol accepts only the scoped kind, silently [13]; the test account had no Jira provisioned at all, only Bitbucket and Trello, so a site had to be created from nothing [14]; and an organisation admin toggle, off by default, blocked API-token auth with an error that pointed at neither the token nor the toggle and just said to ask your admin [15].

What to watch is whether your harness can tell loop exhaustion from action failure. The information needed to do that was already on disk here, in the audit trail with the raw response body from the last mutating call [18]. An abort path that does not read it, and instead hands the operator a bare failure, is asking for a duplicate write.

Loading claim ledger
Loading source directory links
Loading share composer
Loading topic controls
Loading related stories