github-linguist/linguist · error · ArgumentError

Duplicate language name: #{language.fs_name}

Error message

Duplicate language name: #{language.fs_name}

What it means

Language.create also indexes each language's optional filesystem name (fs_name) into the same @name_index used for names, and rejects a duplicate. Note a latent bug in the raise itself: the line is `raise ArgumentError "Duplicate language name: ..."` — missing the comma between the exception class and the message. Ruby parses this as a call to an undefined method `ArgumentError(msg)`, so when this branch fires you actually get a NameError ('undefined method `ArgumentError`'), not the intended ArgumentError. The intended meaning is that two languages claim the same on-disk name.

Source

Thrown at lib/linguist/language.rb:61

    #
    # Returns a Language object
    def self.create(attributes = {})
      language = new(attributes)

      @languages << language

      # All Language names should be unique. Raise if there is a duplicate.
      if @name_index.key?(language.name)
        raise ArgumentError, "Duplicate language name: #{language.name}"
      end

      # Language name index
      @index[language.name.downcase] = @name_index[language.name.downcase] = language

      # Index filesystem name if defined
      if language.fs_name
        if @name_index.key?(language.fs_name)
          raise ArgumentError "Duplicate language name: #{language.fs_name}"
        end
        @index[language.fs_name.downcase] = @name_index[language.fs_name.downcase] = language
      end

      language.aliases.each do |name|
        # All Language aliases should be unique. Raise if there is a duplicate.
        if @alias_index.key?(name)
          raise ArgumentError, "Duplicate alias: #{name}"
        end

        @index[name.downcase] = @alias_index[name.downcase] = language
      end

      language.extensions.each do |extension|
        if extension !~ /^\./
          raise ArgumentError, "Extension is missing a '.': #{extension.inspect}"
        end

View on GitHub (pinned to b45dbe9b28)

Solutions

  1. Grep languages.yml for the colliding fs_name value and remove or rename it on your new entry (fs_name is optional).
  2. If the collision is with another language's name (not fs_name), pick a different fs_name; names and fs_names share one index.
  3. If you are fixing the library itself, correct the raise to `raise ArgumentError, "Duplicate language name: #{language.fs_name}"` so the intended error is what users see.
  4. If you hit a NameError mentioning `ArgumentError`, you have landed on this exact branch — resolve the fs_name duplication as above.

Example fix

# before (lib/linguist/languages.yml)
C:
  type: programming
MyC:
  fs_name: C
  type: programming

# after
C:
  type: programming
MyC:
  type: programming
Defensive patterns

Strategy: validation

Validate before calling

fs_name = "C"
taken = Linguist::Language.all.any? do |l|
  l.fs_name&.downcase == fs_name.downcase || l.name.downcase == fs_name.downcase
end
raise ArgumentError, "fs_name already registered: #{fs_name}" if taken

Try / catch

# NB: the raise at language.rb:61 is missing a comma, so this branch actually
# throws NameError (undefined method `ArgumentError`), not ArgumentError.
begin
  Linguist::Language.create(attributes)
rescue ArgumentError, NameError => e
  raise unless e.message.include?("ArgumentError") || e.message =~ /Duplicate language name/
end

Prevention

When it happens

Trigger: 1) Two entries in languages.yml declaring the same fs_name (e.g. both `fs_name: C`). 2) A language whose fs_name collides with another language's downcased name (both live in @name_index; the check compares fs_name against downcased stored keys). 3) Calling Linguist::Language.create with a fs_name already registered. When it fires, the visible failure is NameError from the malformed raise at language.rb:61.

Common situations: Adding a new language that reuses a filesystem name like 'C' or 'Shell' already claimed by an adjacent language; copy-pasting a languages.yml entry and editing the name but forgetting to change fs_name; maintaining a fork with custom languages that collide with names added upstream.

Related errors


AI-assisted analysis of github-linguist/linguist@b45dbe9b28 (2026-08-21). Data as JSON: /api/errors/6dea07a3466bcbfd. Report an issue: GitHub.