Skip to content

[BUG] Agent: "invalid transition from Idle to Idle" error logged on every run #725

Description

@edenreich

Summary

Every agent run (once per user message/turn) logs an error-level line with a full stacktrace:
failed to transition to Idle state / invalid transition from Idle to Idle. It is harmless - the
agent's state machine is constructed in Idle and Start() redundantly asks it to transition to Idle
again - but because it is logged at error level (and zap's production config attaches a stacktrace to
every error), it reads as a real failure and spams the log on every turn.

Steps to Reproduce

  1. infer chat.
  2. Send any message (triggers an agent run).
  3. Inspect the day's log:
    grep -c "invalid transition from Idle to Idle" ~/.infer/logs/app-$(date +%F).log - one error (plus a
    multi-line stacktrace) per run.

Expected Behavior

Starting the agent while it is already in Idle is a no-op, not an error. Nothing should be logged at
error level (and no stacktrace) for this.

Actual Behavior

{"level":"error","caller":"agent/agent_event_driven.go:200","msg":"failed to transition to Idle state","error":"invalid transition from Idle to Idle","stacktrace":"github.com/inference-gateway/cli/internal/agent.(*EventDrivenAgent).Start\n\t.../agent/agent_event_driven.go:200\ngithub.com/inference-gateway/cli/internal/agent.(*AgentServiceImpl).RunWithStream.func1\n\t.../agent/agent.go:647"}

Root Cause

  • NewAgentStateMachine initializes currentState: domain.StateIdle (internal/agent/agent_state_machine.go:59),
    and a fresh state machine is constructed for every agent run (internal/agent/agent_event_driven.go:69,
    called from AgentServiceImpl.RunWithStream per request).
  • EventDrivenAgent.Start() then unconditionally calls
    a.stateMachine.Transition(a.agentCtx, domain.StateIdle) (agent_event_driven.go:199).
  • The only outgoing transition registered from Idle is Idle -> CheckingQueue
    (agent_state_machine.go:76); there is no Idle -> Idle self-transition, so findTransition returns
    nil and Transition returns invalid transition from Idle to Idle (agent_state_machine.go:202-205).
  • Start() logs that error (agent_event_driven.go:200).

The subsequent MessageReceivedEvent drives the real Idle -> CheckingQueue flow, so there is no
functional impact
- only a misleading, per-turn error + stacktrace in the log.

Proposed Fix

Either:

  • Guard the redundant call in Start() - only transition when not already in Idle
    (if a.stateMachine.GetCurrentState() != domain.StateIdle { ... }), or drop the initializing
    transition entirely since the machine is always constructed in Idle. Minimal, localized.
  • Or make Transition treat a same-state target as a successful no-op
    (if sm.currentState == targetState { return nil } before findTransition), which resolves this class
    of redundant self-transition everywhere.

Recommend the localized Start() guard unless a general same-state no-op policy is preferred.

Environment

inference-gateway/cli, main. Surfaced right after #722 removed the unrelated keybinding log noise, so
pre-existing agent-level errors are now visible.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingreleased

    Type

    Fields

    No fields configured for Bug.

    Projects

    Status
    Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions