gitlabhq/gitlabhq · error · KeysFinder::InvalidFingerprint
Failed to return the key
Error message
Failed to return the key
What it means
KeysFinder#by_fingerprint raises InvalidFingerprint (rendered by the keys API as HTTP 400 'Failed to return the key', lib/api/keys.rb) when the fingerprint parameter fails validation. A SHA256 fingerprint (recognized by its sha256:/SHA256: prefix) must Base64-decode to exactly 32 bytes; an MD5 fingerprint must match 16 colon-separated hex pairs - and MD5 is rejected outright when the instance runs in FIPS mode.
Source
Thrown at app/finders/keys_finder.rb:78
keys.created_after(params[:created_after])
end
def by_expires_before(keys)
return keys unless params[:expires_before]
keys.expires_before(params[:expires_before])
end
def by_expires_after(keys)
return keys unless params[:expires_after]
keys.expires_after(params[:expires_after])
end
def by_fingerprint(keys)
return keys unless params[:fingerprint].present?
raise InvalidFingerprint unless valid_fingerprint_param?
keys.find_by(fingerprint_query) # rubocop:disable CodeReuse/ActiveRecord -- find_by needed for fingerprint lookup
end
def valid_fingerprint_param?
return Base64.decode64(fingerprint).length == 32 if fingerprint_type == "sha256"
return false if Gitlab::FIPS.enabled?
fingerprint =~ /^(\h{2}:){15}\h{2}/
end
def fingerprint_query
fingerprint_attribute = FINGERPRINT_ATTRIBUTES[fingerprint_type]
Key.arel_table[fingerprint_attribute].eq(fingerprint)
end
View on GitHub (pinned to 55ee20384a)
Solutions
- Use the SHA256 form: the literal prefix sha256: followed by the base64 digest that decodes to 32 bytes - exactly what `ssh-keygen -lf key.pub` prints.
- If you must use MD5, ensure the format is exactly 16 lowercase hex pairs separated by colons (aa:bb:...), but prefer migrating to SHA256.
- On FIPS instances, switch entirely to SHA256 fingerprints - MD5 lookups cannot work there.
- Copy the fingerprint from `GET /keys` output or the user's profile page rather than re-typing it.
Example fix
# before: hex-encoded sha256 digest is not valid GET /api/v4/keys?fingerprint=SHA256:1f2e3d4c5b6a...64-hex-chars # => 400 Failed to return the key # after: base64 digest as printed by ssh-keygen -lf GET /api/v4/keys?fingerprint=SHA256:H8xP4pCT6mQ0zqF3nJ9yQcVeEr5T5Y+1a2B3c4D5e6F
Defensive patterns
Strategy: validation
Validate before calling
def fingerprint_ok?(fp)
if fp.match?(/sha256:/i)
require 'base64'
Base64.decode64(fp.sub(/sha256:/i, '')).bytesize == 32
else
!Gitlab::FIPS.enabled? && fp.match?(/^([0-9a-f]{2}:){15}[0-9a-f]{2}/)
end
end
render_api_error!('bad fingerprint', 400) unless fingerprint_ok?(params[:fingerprint]) Type guard
def valid_sha256_fingerprint?(fp)
fp.to_s.start_with?('sha256:', 'SHA256:') &&
Base64.decode64(fp.sub(/(sha256:)|(SHA256:)/, '')).bytesize == 32
end Try / catch
begin
key = KeysFinder.new(fingerprint: fp).execute
rescue KeysFinder::InvalidFingerprint
render_api_error!('Failed to return the key', 400) # terminal: fix the fingerprint format, do not retry
end Prevention
- Standardize on SHA256 fingerprints produced by ssh-keygen -lf.
- Validate format (and FIPS mode) before calling the keys API.
- Never reformat fingerprints programmatically - copy them verbatim.
When it happens
Trigger: GET /api/v4/keys?fingerprint=<malformed string>; supplying a SHA256 digest in hex (64 hex chars) instead of base64; sending an MD5 (colon-delimited) fingerprint to a FIPS-enabled GitLab; whitespace or truncation from copy-pasting the fingerprint.
Common situations: Tools that print fingerprints in hex; older scripts written before SHA256 fingerprints became the default; FIPS-compliant self-managed installations where MD5 lookups silently stopped working; UIs that strip colons from MD5 strings.
Related errors
- The requested `version` attribute format is not correct. Use
- Start argument must be before End argument
- `from_line` and `to_line` must be greater than or equal to 1
- TooManyTagsError
- Unknown status `#{new_status}`
AI-assisted analysis of gitlabhq/gitlabhq@55ee20384a (2026-08-21).
Data as JSON: /api/errors/43c0b9d56fa2fa43.
Report an issue: GitHub.