sds/overcommit · error · Overcommit::Exceptions::HookLoadError
Class #{hook_name} is not a subclass of #{hook_base_class}.
Error message
Class #{hook_name} is not a subclass of #{hook_base_class}. What it means
Overcommit resolves each hook by its CamelCase name under the hook type module (e.g. Overcommit::Hook::PreCommit) and requires it to inherit that type's Base class (e.g. Overcommit::Hook::PreCommit::Base). This error means the constant was found but the subclass test (hook_class < hook_base_class in Base#create_hook) failed. Overcommit rejects the class because it would not implement the hook lifecycle API (run, enabled?, skip) that HookRunner depends on.
Source
Thrown at lib/overcommit/hook_loader/base.rb:33
# When implemented in subclasses, loads the hooks for which that subclass is
# responsible.
#
# @return [Array<Hook>]
def load_hooks
raise NotImplementedError
end
private
attr_reader :log
# Load and return a {Hook} from a CamelCase hook name.
def create_hook(hook_name)
hook_type_class = Overcommit::Hook.const_get(@context.hook_class_name)
hook_base_class = hook_type_class.const_get(:Base)
hook_class = hook_type_class.const_get(hook_name)
unless hook_class < hook_base_class
raise Overcommit::Exceptions::HookLoadError,
"Class #{hook_name} is not a subclass of #{hook_base_class}."
end
begin
Overcommit::Hook.const_get(@context.hook_class_name).
const_get(hook_name).
new(@config, @context)
rescue LoadError, NameError => e
raise Overcommit::Exceptions::HookLoadError,
"Unable to load hook '#{hook_name}': #{e}",
e.backtrace
end
end
end
end
View on GitHub (pinned to fee0cd74b2)
Solutions
- Make the class named in the error inherit from the base class shown in the message, e.g. 'class MyPlugin < Overcommit::Hook::PreCommit::Base'
- Confirm the class name is the CamelCase form of the plugin file name (my_plugin.rb -> MyPlugin) inside the module for that hook type directory
- Rename helper classes that shadow the file name so the constant resolves to the real hook class
- If plugin signatures are enabled, run 'overcommit --sign <hook-type>' after the fix so the modified plugin re-signs
Example fix
# before (.overcommit/plugins/pre_commit/my_plugin.rb)
module Overcommit::Hook::PreCommit
class MyPlugin
def run; end
end
end
# after
module Overcommit::Hook::PreCommit
class MyPlugin < Base
def run
:pass
end
end
end Defensive patterns
Strategy: validation
Validate before calling
hook_type = Overcommit::Hook.const_get(context.hook_class_name)
base = hook_type.const_get(:Base)
name = Overcommit::Utils.camel_case(File.basename(plugin_path, '.rb'))
raise "plugin defines no #{name} class" unless hook_type.const_defined?(name)
raise "#{name} must subclass #{base}" unless hook_type.const_get(name) < base Type guard
def valid_plugin?(hook_type_name, hook_name) mod = Overcommit::Hook.const_get(hook_type_name) mod.const_defined?(hook_name) && mod.const_get(hook_name) < mod.const_get(:Base) rescue NameError false end
Try / catch
begin
runner.run
rescue Overcommit::Exceptions::HookLoadError => e
$stderr.puts "Bad plugin definition: #{e.message}"
exit 1
end Prevention
- Start plugins from an existing built-in hook or template so the Base superclass is already correct
- Keep one hook class per plugin file, named exactly after the file
- Add a CI task that requires every file under .overcommit/plugins to catch bad definitions before teammates pull them
When it happens
Trigger: A plugin file loaded from .overcommit/plugins/<hook_type>/ defines or reopens the constant matching its CamelCase file name without inheriting from the hook type's Base - e.g. 'module Overcommit::Hook::PreCommit; class MyPlugin; end; end' with no superclass - or a helper class shadows the name derived from the file name. Raised during load_hooks -> create_hook.
Common situations: Writing a first custom plugin and forgetting the '< Overcommit::Hook::PreCommit::Base' superclass; pasting a plugin template into the wrong hook type namespace; plugin files that only define helper classes and constants.
Related errors
- Unable to load hook '#{hook_name}': #{e}
- Unable to load hook '#{hook_name}': #{e}
- A load error occurred. Did you forget to install a gem? #{e.
- Hook specified a `required_executable` or `command` that is
- Unable to write to local repo git config: #{result.stderr}
AI-assisted analysis of sds/overcommit@fee0cd74b2 (2026-08-23).
Data as JSON: /api/errors/a49536a25658ece6.
Report an issue: GitHub.