basecamp/fizzy · error · ActionPack::WebAuthn::InvalidResponseError
Authenticator data is too short
Error message
Authenticator data is too short
What it means
Authenticator::Data.decode requires at least 37 bytes: 32-byte RP ID hash + 1-byte flags + 4-byte sign count (RELYING_PARTY_ID_HASH_LENGTH + FLAGS_LENGTH + SIGN_COUNT_LENGTH). Input below that cannot be valid authenticator data, so the parser rejects it immediately with InvalidResponseError.
Source
Thrown at lib/action_pack/web_authn/authenticator/data.rb:83
def wrap(data)
if data.is_a?(self)
data
else
data = Base64.urlsafe_decode64(data) unless data.encoding == Encoding::BINARY
decode(data)
end
rescue ArgumentError
raise ActionPack::WebAuthn::InvalidResponseError, "Invalid base64 encoding in authenticator data"
end
# Decodes raw authenticator data bytes into a Data instance, parsing the
# RP ID hash, flags, sign count, and (if present) attested credential data.
def decode(bytes)
bytes = bytes.bytes if bytes.is_a?(String)
minimum_length = RELYING_PARTY_ID_HASH_LENGTH + FLAGS_LENGTH + SIGN_COUNT_LENGTH
if bytes.length < minimum_length
raise ActionPack::WebAuthn::InvalidResponseError, "Authenticator data is too short"
end
position = 0
relying_party_id_hash = bytes[position, RELYING_PARTY_ID_HASH_LENGTH].pack("C*")
position += RELYING_PARTY_ID_HASH_LENGTH
flags = bytes[position]
position += FLAGS_LENGTH
sign_count = bytes[position, SIGN_COUNT_LENGTH].pack("C*").unpack1("N")
position += SIGN_COUNT_LENGTH
aaguid = nil
credential_id = nil
public_key_bytes = nil
if flags & ATTESTED_CREDENTIAL_DATA_FLAG != 0View on GitHub (pinned to 7aabe74580)
Solutions
- Check the decoded byte length in console: Base64.urlsafe_decode64(param).bytesize must be >= 37 (assertion) or >= 37+18+credential-id+key bytes (registration).
- Log bytesize at the trust boundary to confirm where truncation happens (client vs transport vs server).
- Regenerate fixtures from a real browser passkey ceremony (Chrome DevTools or a WebAuthn test harness) instead of hand-writing strings.
- Verify you are passing the authenticatorData field itself, not challenge, userHandle, or clientDataJSON.
Example fix
# before
data = ActionPack::WebAuthn::Authenticator::Data.wrap(params[:authenticator_data])
# after — cheap pre-flight length check
raw = Base64.urlsafe_decode64(params[:authenticator_data].to_s)
if raw.bytesize < 37
return render json: { error: "authenticator data truncated" }, status: :bad_request
end
data = ActionPack::WebAuthn::Authenticator::Data.wrap(raw) Defensive patterns
Strategy: validation
Validate before calling
raw = Base64.urlsafe_decode64(params[:authenticator_data].to_s)
return render(json: { error: 'authenticator data too short' }, status: :bad_request) if raw.bytesize < 37 Type guard
def plausible_authenticator_data?(value) return false unless (decoded = Base64.urlsafe_decode64(value) rescue nil) decoded.bytesize >= 37 end
Try / catch
begin
data = ActionPack::WebAuthn::Authenticator::Data.wrap(raw)
rescue ActionPack::WebAuthn::InvalidResponseError => e
render json: { error: e.message }, status: :bad_request
end Prevention
- Log decoded bytesize for every WebAuthn request during development to catch truncation at the edge.
- Keep fixtures generated from real ceremonies, never hand-typed strings.
- Map every InvalidResponseError to HTTP 400 with the library message — client input is not retryable.
When it happens
Trigger: Passing a base64url string that decodes to fewer than 37 bytes — empty string, a truncated value cut by a client or proxy, a lone SHA-256 hash, or handing the wrong field (e.g. the challenge or the RP ID hash) where authenticator data is expected.
Common situations: Unit-test fixtures fabricated from short strings instead of a real WebAuthn ceremony; a frontend that slices/substring's the authenticatorData buffer; JSON payloads truncated by request-size limits; double-decoding (decoding base64 twice yields short garbage).
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Unexpected end of input
- Invalid base64 encoding in authenticator data
- Authenticator data is too short for attested credential data
- Authenticator data is too short for credential ID and public
- Client data is not valid JSON
AI-assisted analysis of basecamp/fizzy@7aabe74580 (2026-08-21).
Data as JSON: /api/errors/6489a83a774c7a31.
Report an issue: GitHub.