puppetlabs/puppet · error · Puppet::Forge::Errors::SSLVerifyError

Unable to verify the SSL certificate at %{uri}

Error message

Unable to verify the SSL certificate at %{uri}

What it means

When a resource receives events through notify/subscribe relationships, the transaction's event manager calls resource.send(callback) on it (normally :refresh). If that callback raises - a service provider whose restart command fails, an exec whose refreshed command exits non-zero, a provider without restart support - this rescue logs Failed to call refresh with the original exception message, marks the resource status failed_to_restart, records a failed status event, and returns false so the transaction continues with other resources. The full backtrace goes to the resource's log_exception output, visible at debug/trace level.

Source

Thrown at lib/puppet/forge/repository.rb:54

        str = @uri.to_s
        str.chomp!('/')
        str += Puppet::Util.uri_encode(path)
        uri = URI(str)

        headers = { "User-Agent" => user_agent }

        if forge_authorization
          uri.user = nil
          uri.password = nil
          headers["Authorization"] = forge_authorization
        end

        http = Puppet.runtime[:http]
        response = http.get(uri, headers: headers, options: { ssl_context: @ssl_context })
        io.write(response.body) if io.respond_to?(:write)
        response
      rescue Puppet::SSL::CertVerifyError => e
        raise SSLVerifyError.new(:uri => @uri.to_s, :original => e.cause)
      rescue => e
        raise CommunicationError.new(:uri => @uri.to_s, :original => e)
      end
    end

    def forge_authorization
      if Puppet[:forge_authorization]
        Puppet[:forge_authorization]
      elsif Puppet.features.pe_license?
        PELicense.load_license_key.authorization_token
      end
    end

    # Return the local file name containing the data downloaded from the
    # repository at +release+ (e.g. "myuser-mymodule").
    def retrieve(release)
      path = @host.chomp('/') + release
      cache.retrieve(path)

View on GitHub (pinned to e227c27540)

Solutions

  1. Reproduce the refresh by hand as root (systemctl restart nginx; nginx -t) - whatever fails there is the %{detail}.
  2. Run puppet agent -t --debug (or --trace) and read the log_exception backtrace printed next to this message to identify the failing provider call.
  3. Fix the underlying cause: repair the config/template the restart depends on, or install the missing command/init support.
  4. If restart genuinely cannot work on the platform, redirect refresh to something safe: restart => '/usr/sbin/nginx -s reload', or hasrestart => false so refresh falls back to stop/start.
  5. For your own types, implement refresh (and the restart/stop/start it delegates to) instead of letting the default raise.

Example fix

# before: notified restart of a service whose restart command fails -> Failed to call 'refresh'
service { 'nginx':
  ensure    => running,
  subscribe => File['/etc/nginx/nginx.conf'],
}

# after: refresh path validates config and reloads, so the callback cannot raise on bad config
service { 'nginx':
  ensure    => running,
  subscribe => File['/etc/nginx/nginx.conf'],
  restart   => '/usr/sbin/nginx -t && /bin/systemctl reload nginx',
}
Defensive patterns

Strategy: try-catch

Validate before calling

# Spec: prove the callback the event manager will invoke cannot raise
it 'survives the refresh callback' do
  svc = Puppet::Type.type(:service).new(
    name: 'nginx', ensure: :running, provider: :systemd
  )
  expect { svc.provider.refresh }.not_to raise_error
end

Try / catch

# Provider authors: guard the callback so the event manager never sees a raise
def refresh
  return unless resource.should(:ensure) == :running  # no restart while stopped
  systemctl('reload-or-restart', resource[:name])
rescue Puppet::ExecutionFailure => e
  # Narrow rescue only: report and keep the provider consistent
  warning("restart failed: #{e}")
  nil
end

Prevention

When it happens

Trigger: File->Service subscribe where the notified systemctl restart fails because the same run shipped a broken config; Service with restart => '<cmd>' where the command is absent or returns non-zero; providers whose refresh path raises (unsupported restart, missing init system in containers); Mount reload failing on notify; Exec with refreshonly whose command fails only when triggered.

Common situations: Templates that deploy a syntactically invalid app/nginx config and immediately restart the service; minimal containers where service restart commands do not exist; custom in-house types whose provider never implemented refresh or restart.

Understand the failure class

Related errors


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