instructure/canvas-lms · error · ArgumentError
cannot pass both a module_name and a block
Error message
cannot pass both a module_name and a block
What it means
Autoextend.hook is strictly either/or: you may supply a module_name (existing module to mix in) OR a &block (inline module), never both. Supplying both is ambiguous — the gem would not know which extension source to use — so hook raises ArgumentError up front.
Solutions
- Remove the block and keep module_name if the extension lives in an existing module
- Remove the module_name argument and keep the block for an inline extension
- Split into two separate hook calls if both extensions are genuinely needed
Example fix
// before
Autoextend.hook('User', 'UserExtensions', :create) { def extra; end }
// after
Autoextend.hook('User', 'UserExtensions', :create) Defensive patterns
Strategy: validation
Validate before calling
raise 'pass module_name XOR block' if mod_name && block_given?
Try / catch
begin
Autoextend.hook(const_name, mod_name, method, &blk)
rescue ArgumentError => e
Rails.logger.error("ambiguous autoextend hook: #{e.message}")
end Prevention
- Pick one extension style per hook and stick to it
- Lint initializer files for hook calls containing both forms
- Split mixed registrations into separate hook calls
When it happens
Trigger: Calling Autoextend.hook('Model', 'SomeModule', :method) { ... } — a module_name string plus an attached block in the same call.
Common situations: Merging two hook registrations into one call during a refactor; copy-pasting a block-based hook and leaving the old module_name argument in place; IDE snippets that prefill module_name while the developer also writes a block.
Related errors
- block is required if module_name is not passed
- Cannot include a concatenation in a merge.
- Missing required asset parameter #
- Missing required parameter: copied_at
- Missing required parameter: course
AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15).
Data as JSON: /api/errors/f75a5aa167a36cb9.
Report an issue: GitHub.
Appendix: source
Thrown at gems/autoextend/lib/autoextend.rb:66
# If User is already defined, it will immediately include
# the MyUserExtension module into it. It then sets up a hook
# to automatically include in User if it becomes defined again
# (like from ActiveSupport reloading).
#
# You can make an extension optional, which is for information only,
# so that if you have a spec that checks if all extensions were used
# it can ignore optional extensions.
def hook(const_name,
module_name = nil,
method: :include,
singleton: false,
after_load: false,
optional: false,
before: [],
after: [],
&block)
raise ArgumentError, "block is required if module_name is not passed" if !module_name && !block
raise ArgumentError, "cannot pass both a module_name and a block" if module_name && block
extension = Extension.new(const_name,
module_name,
method,
block,
singleton,
optional,
Array(before),
Array(after))
const_extensions = extensions_hash[const_name.to_sym] ||= []
const_extensions << extension
if module_name.is_a?(Module)
module_name = module_name.name
end
# immediately extend the class if it's already definedView on GitHub (pinned to 1c9f0bb801)