github-linguist/linguist · error · ArgumentError

Extension is missing a '.': #{extension.inspect}

Error message

Extension is missing a '.': #{extension.inspect}

What it means

While indexing a language's extensions, Language.create validates that every extension string starts with a literal dot (`extension =~ /^\./`) before adding it to @extension_index. This enforces the registry convention that extensions include the leading separator, e.g. '.rb' not 'rb', which the detection strategies rely on when matching blob paths. Any entry in an `extensions:` list missing the dot raises ArgumentError during the require-time load of languages.yml.

Source

Thrown at lib/linguist/language.rb:77

      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

        @extension_index[extension.downcase] << language
      end

      language.interpreters.each do |interpreter|
        @interpreter_index[interpreter] << language
      end

      language.filenames.each do |filename|
        @filename_index[filename] << language
      end

      @language_id_index[language.language_id] = language

      language
    end

View on GitHub (pinned to b45dbe9b28)

Solutions

  1. Find the extension named in the message and prefix it with a dot in languages.yml (e.g. 'sc' -> '.sc').
  2. Scan the whole extensions list of your new entry — the raise stops at the first bad one, others may follow.
  3. If creating languages programmatically, normalize with `ext.start_with?('.') ? ext : ".#{ext}"` before calling create.
  4. Run the repo's test suite (`bundle exec rake test`) after YAML edits so this is caught before deploy.

Example fix

# before (lib/linguist/languages.yml)
Scala:
  extensions:
    - sc
    - .scala

# after
Scala:
  extensions:
    - .sc
    - .scala
Defensive patterns

Strategy: validation

Validate before calling

extensions = attributes[:extensions].to_a
bad = extensions.reject { |e| e.is_a?(String) && e.start_with?('.') }
raise ArgumentError, "extensions missing leading '.': #{bad.map(&:inspect).join(', ')}" unless bad.empty?

Type guard

def valid_extension?(e)
  e.is_a?(String) && e.match?(/\A\.[^.]*\z/)
end

Try / catch

begin
  Linguist::Language.create(attributes)
rescue ArgumentError => e
  raise if e.message !~ /Extension is missing a '.'/
  attributes[:extensions].map! { |e| e.start_with?('.') ? e : ".#{e}" }
  retry
end

Prevention

When it happens

Trigger: 1) Writing a new entry in languages.yml as `extensions: [sc, .scala]` instead of [.sc, .scala]. 2) Programmatically calling Language.create(extensions: ['rb']). 3) A hand-edited or generated languages_data.rb containing an extension without the leading dot. The message prints the offending value via inspect, so it shows exactly which string failed.

Common situations: First-time contributors adding a language and listing extensions the way users type them (no dot); converting a list from another tool that strips dots; YAML quoting mistakes that turn an extension into a non-string or mangle it.

Understand the failure class

Background: Config validation failed: what "invalid value for {key}" and settings-rejection errors mean across 19 open-source libraries — this error's family across 19 libraries.

Related errors


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