puppetlabs/puppet · error · Puppet::Error

Timed out while waiting for the service to transition from %

Error message

Timed out while waiting for the service to transition from %{initial_state} to %{final_state} OR from %{initial_state} to %{pending_state} to %{final_state}. The service's current state is %{current_state}.

What it means

Raised by wait_on_state_transition when a service does not reach the requested final state within the timeout (DEFAULT_TIMEOUT = 30 seconds, overridable via the timeout: keyword of Service.start/stop/resume, which is what the Windows service provider passes). The message records the from/to states, the intermediate pending state, and the state observed at timeout. It is a Puppet::Error (not a Win32 error) raised after polling with 1-second sleeps.

Source

Thrown at lib/puppet/util/windows/service.rb:624

            state = status[:dwCurrentState]
            return if state == final_state

            if state == pending_state
              Puppet.debug _("The service transitioned to the %{pending_state} state.") % { pending_state: SERVICE_STATES[pending_state] }
              wait_on_pending_state(service, pending_state, timeout)
              return
            end
            sleep(1)
            elapsed_time += 1
          end
        end
        # Timed out while waiting for the transition to finish. Raise an error
        # We can still use the state variable read from the FFI struct because
        # FFI creates new Integer objects during an assignment of an integer value
        # stored in an FFI struct. We verified that the '=' operater is safe
        # from the freed memory since the new ruby object created during the
        # assignment will remain in ruby memory and remain immutable and constant.
        raise Puppet::Error, _("Timed out while waiting for the service to transition from %{initial_state} to %{final_state} OR from %{initial_state} to %{pending_state} to %{final_state}. The service's current state is %{current_state}.") % { initial_state: SERVICE_STATES[initial_state], final_state: SERVICE_STATES[final_state], pending_state: SERVICE_STATES[pending_state], current_state: SERVICE_STATES[state] }
      end
      private :wait_on_state_transition

      # @api private
      # Waits for a service to finish transitioning from
      # a pending state. The service must be in the pending state
      # before invoking this routine.
      #
      # @param [:handle] service handle to the service to wait on
      # @param [Integer] pending_state the pending state
      # @param [Integer] timeout the minumum number of seconds to wait before timing out
      def wait_on_pending_state(service, pending_state, timeout)
        final_state = FINAL_STATES[pending_state]

        Puppet.debug _("Waiting for the pending transition to the %{final_state} state to finish.") % { final_state: SERVICE_STATES[final_state] }

        elapsed_time = 0
        last_checkpoint = -1

View on GitHub (pinned to e227c27540)

Solutions

  1. Pass a larger timeout to the API call: Puppet::Util::Windows::Service.start(service_name, timeout: 120) — the Windows service provider already forwards this pattern.
  2. Measure how long the service actually needs (`sc query` in a loop, or the service's own logs) and set the timeout above that.
  3. Fix the service's slowness: reduce work in ServiceMain, declare/start dependencies first, or increase the service's own dwWaitHint so the SCM does not kill it.
  4. Retry the Puppet run — startup-time spikes during boot or patching are often transient.
  5. Check the application/system event log for the service to see what it was doing when the timeout fired.

Example fix

# before
Puppet::Util::Windows::Service.start(service_name) # waits max 30s (DEFAULT_TIMEOUT)

# after
Puppet::Util::Windows::Service.start(service_name, timeout: 180) # allow slow-starting service
Defensive patterns

Strategy: retry

Validate before calling

# measure the service's real start time before choosing a timeout
started = Time.now
`sc start #{name}`
sleep 1 until `sc query #{name}` =~ /RUNNING/ || Time.now - started > 30
# set your Puppet timeout comfortably above the observed duration

Try / catch

attempts = 0
begin
  attempts += 1
  Puppet::Util::Windows::Service.start(name, timeout: 120)
rescue Puppet::Error => e
  raise unless e.message.include?('Timed out') && attempts < 3
  Puppet.warning("start timeout, retry #{attempts}/3")
  retry
end

Prevention

When it happens

Trigger: Service.start/stop/resume on a service that takes longer than 30 seconds to move (e.g. START_PENDING -> RUNNING); slow shutdown with long shutdown timeouts in the service binary; the service is waiting on a dependency (RPC endpoint mapper, SQL) that is itself slow; heavy load lengthening start beyond the default.

Common situations: Large services (SQL Server, Antivirus, backup agents) on slow VMs; first boot after patching when many services start concurrently; services that block in ServiceMain waiting on network resources; Puppet runs failing transiently during startup storms.

Understand the failure class

Related errors


AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21). Data as JSON: /api/errors/c85058a9e20208bc. Report an issue: GitHub.