visit_Psych_Nodes_Alias: Unknown alias: default (Psych::BadAlias)

The problem is related to the Ruby 3.1 / Psych 4.x incompatibility described in this issue: https://bugs.ruby-lang.org/issues/17866

Ruby 3.0 comes with Psych 3, while Ruby 3.1 comes with Psych 4, which has a major breaking change (diff 3.3.2 → 4.0.0).

  • The new YAML loading methods (Psych 4) do not load aliases unless they get the aliases: true argument.
  • The old YAML loading methods (Psych 3) do not support the aliases keyword.

At this point, it seems like anyone, anywhere that wants to load YAML in the same way it worked prior to Ruby 3.1, need to do something like this:

begin
  YAML.load(source, aliases: true, **options)
rescue ArgumentError
  YAML.load(source, **options)
end

as patched by the Rails team.

In your case, I suspect you will need to see which Rails version that matches your major version preference includes this patch before you can upgrade to Ruby 3.1.

Personally, wherever I have control of the code that loads YAML, I am adding an extension like this:

module YAML
  def self.properly_load_file(path)
    YAML.load_file path, aliases: true
  rescue ArgumentError
    YAML.load_file path
  end
end

or, if I want to completely revert this change done in Psych 4, I add this to my code:

module YAML
  class << self
    alias_method :load, :unsafe_load if YAML.respond_to? :unsafe_load
  end
end

This has the advantage of restoring YAML::load, and YAML::load_file (which uses it) to their original glory, and solves everything including libraries that you have no control of, in all Ruby versions.

Lastly, as I mentioned in the comments, in case you prefer a minimally invasive stopgap measure, you might be able to get away with pinning Psych to < 4 in your Gemfile:

gem 'psych', '< 4'

Note for Rails users (>= 7.0.3.1)

ActiveRecord 7.0.3.1 changed an internal call and it now calls safe_load directly. If you see a Psych related error during rails tests, you might be affected by this change.

To resolve it, you can add this to a new or existing initializer:

# config/initializers/activerecord_yaml.rb
ActiveRecord.use_yaml_unsafe_load = true

You may also use ActiveRecord.yaml_column_permitted_classes to configure the allowed classes instead.

More info in this post.

Leave a Comment