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
Raised when instantiating a hook class fails with LoadError or NameError after the class resolved. Base#create_hook calls Hook::<Type>.const_get(hook_name).new(config, context) and wraps any LoadError/NameError as HookLoadError, keeping the original message and backtrace, because the missing constant or file usually points to an unloaded gem or a plugin file/class name mismatch.
Source
Thrown at lib/overcommit/hook_loader/base.rb:42
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
- Read the tail of the message after the colon - it carries the original NameError/LoadError naming the missing constant or file; fix that first
- If a gem constant is missing, add the require at the top of the plugin file and add the gem to the bundle
- If the hook class was never defined, make the class name the exact CamelCase of the file name (my_check.rb -> MyCheck) inside the correct hook module
- If the dependency lives in another plugin, load it with require_relative or inline it so load order cannot break
Example fix
# before (.overcommit/plugins/pre_commit/json_lint.rb)
module Overcommit::Hook::PreCommit
class JsonLint < Base
def run
JsLint.check(applicable_files) # NameError: uninitialized constant JsLint
end
end
end
# after
require 'js_lint'
module Overcommit::Hook::PreCommit
class JsonLint < Base
def run
JsLint.check(applicable_files)
end
end
end Defensive patterns
Strategy: try-catch
Validate before calling
# CI smoke test: every plugin must load standalone
Dir[File.expand_path('.overcommit/plugins/**/*.rb')].sort.each { |f| require f } Try / catch
begin
hooks = Overcommit::HookLoader::PluginHookLoader.new(config, context, logger).load_hooks
rescue Overcommit::Exceptions::HookLoadError => e
warn "Plugin failed to load: #{e.message}"
warn e.backtrace.first(5)
exit 78 # EX_CONFIG
end Prevention
- require every gem a plugin uses at the top of the plugin file
- Run a rake/CI task that requires all plugins on every push
- Name plugin classes exactly after their file so const_get always resolves
When it happens
Trigger: The plugin class body or its initialize references an uninitialized constant (e.g. a gem class never required); the plugin file never defined the expected CamelCase constant so const_get(hook_name) raises NameError (file my_check.rb defining class MyChek); or plugin code calls require on a file or gem that cannot be found.
Common situations: Plugin uses a gem constant without requiring the gem; typo between plugin file name and class name; plugin depends on a constant defined in another plugin file that sorts later during load; an Overcommit upgrade renamed a hook class the plugin reopened.
Related errors
- Class #{hook_name} is not a subclass of #{hook_base_class}.
- 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/03ce9c02fea2f676.
Report an issue: GitHub.