annotaterb icon indicating copy to clipboard operation
annotaterb copied to clipboard

Crash when using "--nested-position": undefined method `type_map' for an instance of AnnotateRb::ModelAnnotator::FileParser::YmlParser (NoMethodError)

Open wmakley opened this issue 4 months ago • 4 comments

I experienced this crash when using the latest version of this gem against a large project using the command. Hopefully just a simple mistake of calling a method that doesn't exist.

bundle exec annotaterb models --nested-position --force
.local/share/mise/installs/ruby/3.3.8/lib/ruby/gems/3.3.0/gems/annotaterb-4.19.0/lib/annotate_rb/model_annotator/annotated_file/generator.rb:71:in `block in determine_annotation_position': undefined method `type_map' for an instance of AnnotateRb::ModelAnnotator::FileParser::YmlParser (NoMethodError)

          class_entries = parsed.starts.select { |name, _line| parsed.type_map[name] == :class }
                                                                     ^^^^^^^^^
        from /home/wmakley/.local/share/mise/installs/ruby/3.3.8/lib/ruby/gems/3.3.0/gems/annotaterb-4.19.0/lib/annotate_rb/model_annotator/annotated_file/generator.rb:71:in `select'
        from /home/wmakley/.local/share/mise/installs/ruby/3.3.8/lib/ruby/gems/3.3.0/gems/annotaterb-4.19.0/lib/annotate_rb/model_annotator/annotated_file/generator.rb:71:in `determine_annotation_position'
        from /home/wmakley/.local/share/mise/installs/ruby/3.3.8/lib/ruby/gems/3.3.0/gems/annotaterb-4.19.0/lib/annotate_rb/model_annotator/annotated_file/generator.rb:50:in `content_annotated_before'
        from /home/wmakley/.local/share/mise/installs/ruby/3.3.8/lib/ruby/gems/3.3.0/gems/annotaterb-4.19.0/lib/annotate_rb/model_annotator/annotated_file/generator.rb:41:in `generate'
        from /home/wmakley/.local/share/mise/installs/ruby/3.3.8/lib/ruby/gems/3.3.0/gems/annotaterb-4.19.0/lib/annotate_rb/model_annotator/single_file_annotator.rb:46:in `call'
        from /home/wmakley/.local/share/mise/installs/ruby/3.3.8/lib/ruby/gems/3.3.0/gems/annotaterb-4.19.0/lib/annotate_rb/model_annotator/single_file_annotator.rb:8:in `call_with_instructions'
        from /home/wmakley/.local/share/mise/installs/ruby/3.3.8/lib/ruby/gems/3.3.0/gems/annotaterb-4.19.0/lib/annotate_rb/model_annotator/project_annotator.rb:22:in `block in annotate'
        from /home/wmakley/.local/share/mise/installs/ruby/3.3.8/lib/ruby/gems/3.3.0/gems/annotaterb-4.19.0/lib/annotate_rb/model_annotator/project_annotator.rb:21:in `map'
        from /home/wmakley/.local/share/mise/installs/ruby/3.3.8/lib/ruby/gems/3.3.0/gems/annotaterb-4.19.0/lib/annotate_rb/model_annotator/project_annotator.rb:21:in `annotate'
        from /home/wmakley/.local/share/mise/installs/ruby/3.3.8/lib/ruby/gems/3.3.0/gems/annotaterb-4.19.0/lib/annotate_rb/model_annotator/annotator.rb:21:in `do_annotations'
        from /home/wmakley/.local/share/mise/installs/ruby/3.3.8/lib/ruby/gems/3.3.0/gems/annotaterb-4.19.0/lib/annotate_rb/model_annotator/annotator.rb:8:in `do_annotations'
        from /home/wmakley/.local/share/mise/installs/ruby/3.3.8/lib/ruby/gems/3.3.0/gems/annotaterb-4.19.0/lib/annotate_rb/commands/annotate_models.rb:17:in `call'
        from /home/wmakley/.local/share/mise/installs/ruby/3.3.8/lib/ruby/gems/3.3.0/gems/annotaterb-4.19.0/lib/annotate_rb/runner.rb:38:in `run'
        from /home/wmakley/.local/share/mise/installs/ruby/3.3.8/lib/ruby/gems/3.3.0/gems/annotaterb-4.19.0/lib/annotate_rb/runner.rb:11:in `run'
        from /home/wmakley/.local/share/mise/installs/ruby/3.3.8/lib/ruby/gems/3.3.0/gems/annotaterb-4.19.0/exe/annotaterb:18:in `<top (required)>'
        from /home/wmakley/.local/share/mise/installs/ruby/3.3.8/bin/annotaterb:25:in `load'
        from /home/wmakley/.local/share/mise/installs/ruby/3.3.8/bin/annotaterb:25:in `<top (required)>'
        from /home/wmakley/.local/share/mise/installs/ruby/3.3.8/lib/ruby/gems/3.3.0/gems/bundler-2.6.9/lib/bundler/cli/exec.rb:59:in `load'
        from /home/wmakley/.local/share/mise/installs/ruby/3.3.8/lib/ruby/gems/3.3.0/gems/bundler-2.6.9/lib/bundler/cli/exec.rb:59:in `kernel_load'
        from /home/wmakley/.local/share/mise/installs/ruby/3.3.8/lib/ruby/gems/3.3.0/gems/bundler-2.6.9/lib/bundler/cli/exec.rb:23:in `run'
        from /home/wmakley/.local/share/mise/installs/ruby/3.3.8/lib/ruby/gems/3.3.0/gems/bundler-2.6.9/lib/bundler/cli.rb:452:in `exec'
        from /home/wmakley/.local/share/mise/installs/ruby/3.3.8/lib/ruby/gems/3.3.0/gems/bundler-2.6.9/lib/bundler/vendor/thor/lib/thor/command.rb:28:in `run'
        from /home/wmakley/.local/share/mise/installs/ruby/3.3.8/lib/ruby/gems/3.3.0/gems/bundler-2.6.9/lib/bundler/vendor/thor/lib/thor/invocation.rb:127:in `invoke_command'
        from /home/wmakley/.local/share/mise/installs/ruby/3.3.8/lib/ruby/gems/3.3.0/gems/bundler-2.6.9/lib/bundler/vendor/thor/lib/thor.rb:538:in `dispatch'
        from /home/wmakley/.local/share/mise/installs/ruby/3.3.8/lib/ruby/gems/3.3.0/gems/bundler-2.6.9/lib/bundler/cli.rb:35:in `dispatch'
        from /home/wmakley/.local/share/mise/installs/ruby/3.3.8/lib/ruby/gems/3.3.0/gems/bundler-2.6.9/lib/bundler/vendor/thor/lib/thor/base.rb:584:in `start'
        from /home/wmakley/.local/share/mise/installs/ruby/3.3.8/lib/ruby/gems/3.3.0/gems/bundler-2.6.9/lib/bundler/cli.rb:29:in `start'
        from /home/wmakley/.local/share/mise/installs/ruby/3.3.8/lib/ruby/gems/3.3.0/gems/bundler-2.6.9/exe/bundle:28:in `block in <top (required)>'
        from /home/wmakley/.local/share/mise/installs/ruby/3.3.8/lib/ruby/gems/3.3.0/gems/bundler-2.6.9/lib/bundler/friendly_errors.rb:117:in `with_friendly_errors'
        from /home/wmakley/.local/share/mise/installs/ruby/3.3.8/lib/ruby/gems/3.3.0/gems/bundler-2.6.9/exe/bundle:20:in `<top (required)>'
        from /home/wmakley/.local/share/mise/installs/ruby/3.3.8/bin/bundle:25:in `load'
        from /home/wmakley/.local/share/mise/installs/ruby/3.3.8/bin/bundle:25:in `<main>'

wmakley avatar Sep 23 '25 14:09 wmakley

Hi @wmakley,

Thank you for submitting such a detailed bug report ! The stacktrace was extremely helpful and allowed us to quickly identify the precise cause of the issue.

You were right that it's a NoMethodError, and here is a more accurate breakdown of why it happens:

The annotaterb gem uses Ruby's built-in Ripper library to parse .rb files. This works with an event-based system. We've defined an on_class callback that populates a type_map hash whenever a class keyword is found. The --nested-position logic then uses this type_map to locate class definitions for smart placement of annotations.

For other file types like .yml (e.g., fixtures), the gem correctly switches to a different parser, YmlParser. This parser is designed for YAML and does not have the on_class callback or a type_map, as the concept of a Ruby class doesn't exist in YAML.

The bug occurs because the --nested-position code unconditionally attempts to access this type_map on the parsed object, without first checking if the current file's parser (YmlParser in this case) actually supports it. This results in the NoMethodError you observed.

Thanks again for the excellent report, which helped clarify the precise cause.

Either I or someone else will work on a fix when we have some time, so please bear with us. If you’d like to submit a fix PR yourself, you are more than welcome to do so. 👍

OdenTakashi avatar Sep 24 '25 11:09 OdenTakashi

Hi @wmakley apologies on delay in response -- but you would need to share some of the model files that you're trying to annotate. The explanation that @OdenTakashi seems correct and is dependent on annotated files.

This gem changed from its predecessor by using a class to parse an annotated file. The old gem used a regex which was hard to understand and iterate on.

drwl avatar Oct 20 '25 01:10 drwl

I can't share the code, it's proprietary. Is there any way I can find out what model is crashing?

On October 19, 2025, William Makley @.***> wrote:

drwl left a comment (drwl/annotaterb#270) <https://github.com/drwl/annotaterb/issues/270#issuecomment- 3420234096>

Hi @wmakley https://github.com/wmakley apologies on delay in response -- but you would need to share some of the model files that you're trying to annotate. The explanation that @OdenTakashi https://github.com/OdenTakashi seems correct and is dependent on annotated files.

This gem changed from its predecessor by using a class to parse an annotated file. The old gem used a regex which was hard to understand and iterate on. — Reply to this email directly, view it on GitHub <https://github.com/drwl/annotaterb/issues/270#issuecomment- 3420234096>, or unsubscribe <https://github.com/notifications/unsubscribe- auth/AAD5RDIQIB664MNQJKCUJVD3YQ5M7AVCNFSM6AAAAACHIZ3X26VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZTIMRQGIZTIMBZGY>. You are receiving this because you were mentioned.Message ID: @.***>

wmakley avatar Oct 27 '25 13:10 wmakley

At the moment, there’s no built-in way to identify which file is causing the crash. It’s likely related to a .yml file being parsed when using --nested-position.

As a temporary workaround, you can skip annotation for YAML files by adding this option. There’s also an option to exclude fixtures if you’re using them:

bundle exec annotaterb models --nested-position --force --exclude fixtures

This should help prevent the crash.

If you really want to find out which file is causing it, you can probably do so by modifying the gem source and adding some debug output. We’re planning to fix this in a future release, so please wait for the update. 🙏

OdenTakashi avatar Oct 29 '25 12:10 OdenTakashi