sds/overcommit · error · Overcommit::Exceptions::HookLoadError

Unable to load hook '#{hook_name}': #{e}

Error message

Unable to load hook '#{hook_name}': #{e}

What it means

The ad hoc twin of the create_hook failure: for hooks declared only in .overcommit.yml (no plugin file), PluginHookLoader#create_ad_hoc_hook builds an anonymous subclass of the hook type's Base and registers it with const_set. The rescue fires when Overcommit::Hook.const_get(@context.hook_class_name) or const_get('Base') raises NameError - the configured hook type has no matching module or Base class - and wraps it as 'Unable to load hook'.

Source

Thrown at lib/overcommit/hook_loader/plugin_hook_loader.rb:97

      hook_base = hook_module.const_get('Base')

      # Implement a simple class that executes the command and returns pass/fail
      # based on the exit status
      hook_class = Class.new(hook_base) do
        def run
          result = @context.execute_hook(command)

          if result.success?
            :pass
          else
            [:fail, result.stdout + result.stderr]
          end
        end
      end

      hook_module.const_set(hook_name, hook_class).new(@config, @context)
    rescue LoadError, NameError => e
      raise Overcommit::Exceptions::HookLoadError,
            "Unable to load hook '#{hook_name}': #{e}",
            e.backtrace
    end
  end
end

View on GitHub (pinned to fee0cd74b2)

Solutions

  1. Check the wrapped NameError in the message - it names the constant that could not be resolved
  2. Spell hook type sections with Overcommit's exact CamelCase names (PreCommit:, CommitMsg:, PrePush:) and put ad hoc hooks under those keys
  3. Confirm the hook type exists in your installed version via 'overcommit --list' or Overcommit::Utils.supported_hook_types
  4. Upgrade the overcommit gem if the config targets a newer hook type

Example fix

# before (.overcommit.yml)
Precommit:
  MyCheck:
    required_executable: ./bin/check.sh

# after
PreCommit:
  MyCheck:
    required_executable: ./bin/check.sh
Defensive patterns

Strategy: validation

Validate before calling

require 'yaml'
config = YAML.load_file('.overcommit.yml')
known = %w[plugin_directory gemfile verify_plugin_signatures] +
        Overcommit::Utils.supported_hook_types.map { |t| Overcommit::Utils.camel_case(t) }
unknown = config.keys.map(&:to_s) - known
abort "Unknown hook type section(s): #{unknown.join(', ')}" unless unknown.empty?

Type guard

def supported_hook_section?(key)
  Overcommit::Utils.supported_hook_types.any? { |t| Overcommit::Utils.camel_case(t) == key.to_s }
end

Try / catch

begin
  runner.run
rescue Overcommit::Exceptions::HookLoadError => e
  abort "Fix .overcommit.yml hook type sections: #{e.message}"
end

Prevention

When it happens

Trigger: An enabled ad hoc hook (a config-only entry with required_executable/command) runs during load_hooks when its hook type section does not match a module under Overcommit::Hook - e.g. a misspelled section key like 'Precommit:' instead of 'PreCommit:' - or the installed Overcommit defines no <Type>::Base for that hook type.

Common situations: Typo in a .overcommit.yml section header (Precommit vs PreCommit); copy-pasted config using a hook type the installed Overcommit version does not support; casing changed while refactoring YAML config.

Related errors


AI-assisted analysis of sds/overcommit@fee0cd74b2 (2026-08-23). Data as JSON: /api/errors/ad90a605f6f1b433. Report an issue: GitHub.