github-linguist/linguist · warning · NotImplementedError
read_index is deprecated
Error message
read_index is deprecated
What it means
read_index is a legacy helper on Linguist::Repository that only still works when the underlying source is the Rugged-backed implementation: it raises NotImplementedError ('read_index is deprecated') unless `repository.is_a?(Linguist::Source::RuggedRepository)`. The Repository constructor wraps anything that is not already a Source::Repository in a RuggedRepository for backward compatibility, so the raise specifically means a custom Source::Repository implementation was injected and the old Rugged-specific path (set_attribute_source) cannot run on it. Modern code should use the public analysis API (#language_stats / #cache) instead of this internal helper.
Source
Thrown at lib/linguist/repository.rb:132
# Public: Return the cached results of the analysis
#
# This is a per-file breakdown that can be passed to other instances
# of Linguist::Repository to perform incremental scans
#
# Returns a map of filename => [language, size]
def cache
@cache ||= begin
if @old_commit_oid == @commit_oid
@old_stats
else
compute_stats(@old_commit_oid, @old_stats)
end
end
end
def read_index
raise NotImplementedError, "read_index is deprecated" unless repository.is_a? Linguist::Source::RuggedRepository
repository.set_attribute_source(@commit_oid)
end
def current_tree
raise NotImplementedError, "current_tree is deprecated" unless repository.is_a? Linguist::Source::RuggedRepository
repository.get_tree(@commit_oid)
end
protected
def compute_stats(old_commit_oid, cache = nil)
return {} if repository.get_tree_size(@commit_oid, @max_tree_size) >= @max_tree_size
repository.set_attribute_source(@commit_oid)
diff = repository.diff(old_commit_oid, @commit_oid)
# Clear file map and fetch full diff if any .gitattributes files are changed
if cache && diff.each_delta.any? { |delta| File.basename(delta.new_file[:path]) == ".gitattributes" }
diff = repository.diff(nil, @commit_oid)View on GitHub (pinned to b45dbe9b28)
Solutions
- Replace the read_index call with the public API: `repo.language_stats` (or `repo.cache`) which works for every source implementation.
- If you truly need the git-attributes side effect, call `repo.repository.set_attribute_source(repo.instance_variable_get(:@commit_oid))` only after checking the source type — or better, keep that logic inside your Rugged adapter.
- If you control the call site and must keep behavior, gate it: `repo.read_index if repo.repository.is_a?(Linguist::Source::RuggedRepository)`.
- Upgrade scripts/tooling that referenced this helper when you bumped the linguist gem version.
Example fix
# before linguist_repo.read_index stats = linguist_repo.language_stats # after stats = linguist_repo.language_stats
Defensive patterns
Strategy: type-guard
Validate before calling
def rugged_backed?(linguist_repo) linguist_repo.repository.is_a?(Linguist::Source::RuggedRepository) end linguist_repo.read_index if rugged_backed?(linguist_repo)
Type guard
def supports_legacy_index?(linguist_repo) linguist_repo.repository.is_a?(Linguist::Source::RuggedRepository) end
Try / catch
begin linguist_repo.read_index rescue NotImplementedError => e raise unless e.message =~ /read_index is deprecated/ # source is not Rugged-backed: rely on language_stats instead end
Prevention
- Prefer the public API (#language_stats, #cache) — it works for every source implementation.
- When injecting a custom Source::Repository, audit call sites for read_index/current_tree leftovers.
- Treat NotImplementedError-on-deprecated-helper as an upgrade TODO, not something to rescue-and-ignore permanently.
When it happens
Trigger: 1) Constructing Linguist::Repository with your own Linguist::Source::Repository implementation and then calling `repo.read_index`. 2) Old application/test code still calling read_index after upgrading to a linguist version that abstracted sources (5.x). 3) Test doubles standing in for the source, which are not RuggedRepository instances.
Common situations: Upgrading github-linguist in a hosting stack that now passes a non-Rugged source adapter; long-lived internal scripts that poke at repository internals; RSpec specs that build a Repository around a fake source and reuse pre-5.x helper calls.
Related errors
- current_tree is deprecated
- Duplicate language name: #{language.name}
- Duplicate language name: #{language.fs_name}
- Duplicate alias: #{name}
- Extension is missing a '.': #{extension.inspect}
AI-assisted analysis of github-linguist/linguist@b45dbe9b28 (2026-08-21).
Data as JSON: /api/errors/2e2be4dd5f388e97.
Report an issue: GitHub.