Crash on blob view due to display of last commit
Reported by @ced in the Matrix channel:
Very frequently browsing content file crashes like https://foss.heptapod.net/tryton/tryton/-/blob/branch/default/modules/stock_split/stock.py The request GET https://foss.heptapod.net/tryton/tryton/-/blob/branch/default/modules/stock_split/stock.py?format=json&viewer=simple returns 500
Corresponding abridged logs:
{
"exception.class": "NoMethodError",
"exception.message": "undefined method `sha' for nil:NilClass",
"exception.backtrace": [
"app/controllers/projects/blob_controller.rb:280:in `set_last_commit_sha'",
"app/controllers/projects/blob_controller.rb:294:in `show_json'",
"app/controllers/projects/blob_controller.rb:85:in `block (2 levels) in show'",
"app/controllers/projects/blob_controller.rb:77:in `show'"]
}
Now the surprise is that it does not use the gRPC LastCommitForPath
method, but FindCommits
instead.
lib/gitlab/git/commit.rb
:
def where(options)
repo = options.delete(:repo)
raise 'Gitlab::Git::Repository is required' unless repo.respond_to?(:log)
repo.log(options)
end
# (...)
def last_for_path(repo, ref, path = nil, literal_pathspec: false)
# rubocop: disable Rails/FindBy
# This is not where..first from ActiveRecord
where(
repo: repo,
ref: ref,
path: path,
limit: 1,
literal_pathspec: literal_pathspec
).first
# rubocop: enable Rails/FindBy
end
and of course, lib/gitlab/git/repository.rb
:
def log(options)
default_options = {
limit: 10,
offset: 0,
path: nil,
author: nil,
follow: false,
skip_merges: false,
after: nil,
before: nil,
all: false
}
options = default_options.merge(options)
options[:offset] ||= 0
limit = options[:limit]
if limit == 0 || !limit.is_a?(Integer)
raise ArgumentError, "invalid Repository#log limit: #{limit.inspect}"
end
wrapped_gitaly_errors do
gitaly_commit_client.find_commits(options)
end
end
(all these files are identical in branches heptapod-oldstable
and heptapod-0-41
)
The FindCommits
call itself in HGitaly logs:
191325:[2024-01-25 10:52:06,374] [correlation_id=01HN03Z4MMSPB90878C7YFT4VP] [15017] [INFO] [hgitaly.service.interceptors] Starting to process RPC FindCommitsRequest { repository { storage_name: "default" relative_path: "@hashed/0c/62/0c62cc42d6479a691f03083654ab6a7a84229ab156c948ba8d3b6c79ddd95536.git" gl_repository: "project-1049" gl_project_path: "tryton/tryton" } revision: "branch/default" limit: 1 paths: "modules/stock_split/stock.py" disable_walk: true global_options { literal_pathspecs: true } }
So it looks like FindCommits
returned an empty list, on which .first
returned nil
, and the question is why.
Local hg
calls with ::default
or same which actual node id found in GitLab branches state file are correct:
hg log -r 'reverse(::7bbbb91621ab3759dfdc04de3aa1754c89ef145d)' modules/stock_split/stock.py
changeset: 100125:184cee9c3825
user: Cédric Krier <ced@b2ck.com>
date: Sun Aug 20 12:17:27 2023 +0200
summary: Normalize Unit of Measure labels
changeset: 100120:7129f417a22c
user: Cédric Krier <ced@b2ck.com>
date: Tue Aug 22 13:18:33 2023 +0200
summary: Rename Uom to Unit for move and inventory