basecamp/fizzy · error · ActionPack::WebAuthn::InvalidCborError
Unexpected end of input
Error message
Unexpected end of input
What it means
CborDecoder#decode raises InvalidCborError when the read position is at or past the end of the buffer. At the top level this means empty input; inside nested structures it means a definite-length array or map declared more elements than the buffer actually contains.
Source
Thrown at lib/action_pack/web_authn/cbor_decoder.rb:112
# # => {"a" => 1, "b" => 2}
def decode(bytes, **args)
bytes = bytes.bytes if bytes.respond_to?(:bytes)
new(bytes, **args).decode
end
end
def initialize(bytes, max_depth: MAX_DEPTH, max_size: MAX_SIZE) # :nodoc:
raise ActionPack::WebAuthn::InvalidCborError, "Input exceeds maximum size" if bytes.length > max_size
@bytes = bytes
@max_depth = max_depth
@position = 0
@depth = 0
end
# Decodes the next CBOR data item from the byte sequence.
def decode
raise ActionPack::WebAuthn::InvalidCborError, "Unexpected end of input" if @position >= @bytes.length
raise ActionPack::WebAuthn::InvalidCborError, "Maximum nesting depth exceeded" if @depth >= @max_depth
@depth += 1
result = case major_type
when UNSIGNED_INTEGER_TYPE then decode_unsigned_integer
when NEGATIVE_INTEGER_TYPE then decode_negative_integer
when BYTE_STRING_TYPE then decode_byte_string
when TEXT_STRING_TYPE then decode_text_string
when ARRAY_TYPE then decode_array
when MAP_TYPE then decode_map
when TAG_TYPE then decode_tag
when FLOAT_OR_SIMPLE_TYPE then decode_float_or_simple
end
@depth -= 1
result
endView on GitHub (pinned to 7aabe74580)
Solutions
- Check the input is non-empty before decoding: raise early if bytes.length.zero?.
- Validate the payload length against the declared structure (a quick manual parse of the first header byte) in tests.
- Regenerate the CBOR with a known encoder and compare byte-for-byte to find the truncation point.
- Rescue ActionPack::WebAuthn::InvalidCborError at the boundary and return 400 — truncated client input is not retryable.
Example fix
# before
value = ActionPack::WebAuthn::CborDecoder.decode(params[:attestation_object].to_s)
# after — reject empty/truncated input early with a clear message
raw = params[:attestation_object].to_s
return render(json: { error: 'attestation object missing' }, status: :bad_request) if raw.blank?
value = ActionPack::WebAuthn::CborDecoder.decode(raw) Defensive patterns
Strategy: validation
Validate before calling
return render(json: { error: 'empty CBOR input' }, status: :bad_request) if bytes.nil? || bytes.length.zero?
value = ActionPack::WebAuthn::CborDecoder.decode(bytes) Type guard
def decodable_cbor?(bytes) !bytes.nil? && bytes.length.positive? && bytes.bytesize <= ActionPack::WebAuthn::CborDecoder::MAX_SIZE end
Try / catch
begin
value = ActionPack::WebAuthn::CborDecoder.decode(bytes)
rescue ActionPack::WebAuthn::InvalidCborError => e
render json: { error: "malformed CBOR: #{e.message}" }, status: :bad_request
end Prevention
- Reject empty payloads at the boundary with a field-specific message.
- Round-trip test encoders: decode(encode(x)) == x catches declared-vs-actual count mismatches.
- Never build CBOR by string concatenation of fragments.
When it happens
Trigger: CborDecoder.decode('') or decode([]); an array header like \x83 (3 items) with only 2 items in the buffer; a map header claiming N pairs where the buffer ends early; trailing break-code confusion that leaves position at end when another item is requested.
Common situations: Truncated attestation objects fed to the decoder; fixtures built by concatenating fragments; a client that slices CBOR at the wrong offset (e.g. off-by-one after the flags byte); buffers built with String#slice on multibyte strings.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Authenticator data is too short
- Authenticator data is too short for attested credential data
- Authenticator data is too short for credential ID and public
- Input exceeds maximum size
- Invalid simple value: #{info}
AI-assisted analysis of basecamp/fizzy@7aabe74580 (2026-08-21).
Data as JSON: /api/errors/576309adf517d7ab.
Report an issue: GitHub.