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
infer chat.
- Send any message (triggers an agent run).
- 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.
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 - theagent's state machine is constructed in
IdleandStart()redundantly asks it to transition toIdleagain - 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
infer chat.grep -c "invalid transition from Idle to Idle" ~/.infer/logs/app-$(date +%F).log- one error (plus amulti-line stacktrace) per run.
Expected Behavior
Starting the agent while it is already in
Idleis a no-op, not an error. Nothing should be logged aterror 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
NewAgentStateMachineinitializescurrentState: 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.RunWithStreamper request).EventDrivenAgent.Start()then unconditionally callsa.stateMachine.Transition(a.agentCtx, domain.StateIdle)(agent_event_driven.go:199).IdleisIdle -> CheckingQueue(
agent_state_machine.go:76); there is noIdle -> Idleself-transition, sofindTransitionreturnsnil and
Transitionreturnsinvalid transition from Idle to Idle(agent_state_machine.go:202-205).Start()logs that error (agent_event_driven.go:200).The subsequent
MessageReceivedEventdrives the realIdle -> CheckingQueueflow, so there is nofunctional impact - only a misleading, per-turn error + stacktrace in the log.
Proposed Fix
Either:
Start()- only transition when not already inIdle(
if a.stateMachine.GetCurrentState() != domain.StateIdle { ... }), or drop the initializingtransition entirely since the machine is always constructed in
Idle. Minimal, localized.Transitiontreat a same-state target as a successful no-op(
if sm.currentState == targetState { return nil }beforefindTransition), which resolves this classof 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, sopre-existing agent-level errors are now visible.