puppetlabs/puppet · error · Puppet::Error
The service must be in one of the %{valid_initial_states} st
Error message
The service must be in one of the %{valid_initial_states} states to perform this transition. It is currently in the %{current_state} state. What it means
Raised inside transition_service_state when the service's current state is not among the valid initial states for the requested transition. start() only accepts STOPPED, STOP_PENDING, and START_PENDING; stop() accepts everything except STOPPED; resume() requires PAUSED/PAUSE_PENDING. So, for example, starting a paused service or resuming a running one trips this before any control call is made.
Source
Thrown at lib/puppet/util/windows/service.rb:362
open_service(service_name, SC_MANAGER_CONNECT, service_access) do |service|
query_status(service) do |status|
initial_state = status[:dwCurrentState]
# If the service is already in the final_state, then
# no further work needs to be done
if initial_state == final_state
Puppet.debug _("The service is already in the %{final_state} state. No further work needs to be done.") % { final_state: SERVICE_STATES[final_state] }
next
end
# Check that initial_state corresponds to a valid
# initial state
unless valid_initial_states.include?(initial_state)
valid_initial_states_str = valid_initial_states.map do |state|
SERVICE_STATES[state]
end.join(", ")
raise Puppet::Error, _("The service must be in one of the %{valid_initial_states} states to perform this transition. It is currently in the %{current_state} state.") % { valid_initial_states: valid_initial_states_str, current_state: SERVICE_STATES[initial_state] }
end
# Check if there's a pending transition to the final_state. If so, then wait for
# that transition to finish.
possible_pending_states = FINAL_STATES.keys.select do |pending_state|
# SERVICE_RUNNING has two pending states, SERVICE_START_PENDING and
# SERVICE_CONTINUE_PENDING. That is why we need the #select here
FINAL_STATES[pending_state] == final_state
end
if possible_pending_states.include?(initial_state)
Puppet.debug _("There is already a pending transition to the %{final_state} state for the %{service_name} service.") % { final_state: SERVICE_STATES[final_state], service_name: service_name }
wait_on_pending_state(service, initial_state, timeout)
next
end
# If we are in an unsafe pending state like SERVICE_START_PENDING
# or SERVICE_STOP_PENDING, then we want to wait for that pendingView on GitHub (pinned to e227c27540)
Solutions
- Query Puppet::Util::Windows::Service.service_state(service_name) and branch before calling start/stop/resume
- For start, first resume-or-stop a paused service (or set it to stopped) so it lands in an accepted initial state
- Re-fetch state and retry once on this specific error, since state may have changed between check and call
- Reduce concurrent external service control (monitoring restarts) while the code transitions services
Example fix
// before
Puppet::Util::Windows::Service.start('myservice')
# after
state = Puppet::Util::Windows::Service.service_state('myservice')
if state == :SERVICE_PAUSED
# paused is not a valid initial state for start
Puppet::Util::Windows::Service.stop('myservice')
end
Puppet::Util::Windows::Service.start('myservice') Defensive patterns
Strategy: validation
Validate before calling
state = Puppet::Util::Windows::Service.service_state(name) VALID_FOR_START = [:SERVICE_STOPPED, :SERVICE_STOP_PENDING, :SERVICE_START_PENDING].freeze unless VALID_FOR_START.include?(state) Puppet::Util::Windows::Service.stop(name) if state == :SERVICE_PAUSED end Puppet::Util::Windows::Service.start(name)
Type guard
def startable_state?(state) [:SERVICE_STOPPED, :SERVICE_STOP_PENDING, :SERVICE_START_PENDING].include?(state) end
Try / catch
begin
Puppet::Util::Windows::Service.start(name)
rescue Puppet::Error => e
retry if e.message.include?('must be in one of the') # state changed between check and call
raise
end Prevention
- Query service_state and branch per-API allowed initial states before transitioning
- Treat 'paused' as a state start() rejects; stop or resume it first
- Expect one retry: state can change between your check and the transition
When it happens
Trigger: Calling start while the service is SERVICE_PAUSED or SERVICE_PAUSE_PENDING; calling resume on a service that is SERVICE_RUNNING; calling stop on an already-stopped service raced between the exists/state check and the transition; any transition attempted from a state the API's valid_initial_states list excludes.
Common situations: Idempotency code that assumes 'running' without checking state first; races where another admin or monitor changes service state concurrently; manifests that both stop and start a service in the same run while it is mid-transition.
Related errors
- Unknown Service state '%{current_state}' for '%{service_name
- Unknown start type '%{start_type}' for '%{service_name}'
- Failed to fetch services
- Failed to open a handle to the service
- Failed to open a handle to the service control manager
AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21).
Data as JSON: /api/errors/3a3542e6b1618455.
Report an issue: GitHub.