in3rsha/sha256-animation · error
Invalid hex string: #{input}
Error message
Invalid hex string: #{input} What it means
The counterpart of the binary check in input_type() (sha256lib.rb): an argument starting with 0x must have a remainder that fully matches ^[0-9A-F]+$ case-insensitively — at least one character, hex digits only. Anything else, including an empty payload after 0x, prints this message and exits before hashing starts. The guard exists because the next step, bytes(), feeds the payload straight into Ruby pack('H*'), which cannot convert non-hex characters.
Source
Thrown at sha256lib.rb:84
# Detect input type base on prefix (i.e. binary, hex, or otherwise just a string)
def input_type(input)
# Check if input is referencing a file
if(File.file?(input))
return "file"
else
# Check for hex or binary prefix
case input[0..1]
when "0b"
# check it's a valid binary string
if input[2..-1] =~ /[^0-1]/ # only 1s and 0s
puts "Invalid binary string: #{input}"
exit
end
return "binary"
when "0x"
# check it's a valid hex string
if input[2..-1] !~ /^[0-9A-F]+$/i # only hex chars (case-insensitive)
puts "Invalid hex string: #{input}"
exit
end
return "hex"
else
return "string"
end
end
end
# Convert input (hex, ascii) to array of bytes
def bytes(input, type)
case type
when "binary"
bin = input[2..-1] # trim 0b prefix
if (bin.size % 8 == 0) # if we have been given a bitstring that makes up an exact number of bytes (8 bits in a byte)
bytes = bin.scan(/.{8}/).map {|byte| byte.to_i(2)} # convert the bits to array of bytes (in decimal)
else
bytes = "(bitstring is not an exact amount of bytes)" # helpful noteView on GitHub (pinned to 871e976d69)
Solutions
- Clean the payload after 0x until it contains only 0-9 and a-f/A-F: remove a duplicated 0x, spaces and punctuation
- Give the payload at least one hex digit — a bare '0x' is always rejected
- If the text is meant as plain ASCII, drop the 0x prefix so input_type returns 'string'
- In your own validation, anchor to the true start and end of the string (not ^ and $) and chomp newlines, so a value like 0xabc plus a trailing newline cannot reach pack('H*') and raise ArgumentError there
Example fix
# before ruby sha256.rb '0x0xff12' # -> Invalid hex string: 0x0xff12 ruby sha256.rb '0x' # -> Invalid hex string: 0x # after ruby sha256.rb '0xff12' # valid hex (case-insensitive)
Defensive patterns
Strategy: validation
Validate before calling
# run before input_type() or the sha256.rb CLI
payload = input.to_s.chomp[2..].to_s
bad_hex = input.to_s.start_with?('0x') && (payload.empty? || payload.match(/[^0-9a-fA-F]/))
abort 'payload after 0x must be non-empty hex digits' if bad_hex
type = input_type(input) Type guard
def valid_hex_literal?(s)
text = s.to_s
payload = text.chomp[2..].to_s
!text.start_with?('0x') || (!payload.empty? && payload.match(/[^0-9a-fA-F]/).nil?)
end Try / catch
begin type = input_type(candidate) rescue SystemExit warn 'sha256lib rejected the hex input' end
Prevention
- chomp values from command substitution before passing them — a trailing newline survives this check only to raise ArgumentError inside pack('H*')
- Concatenate payloads, never prefixes: build '0x' + payload once so the prefix is never doubled
- In your own checks anchor to true string boundaries, not ^ and $, to catch trailing newlines
- Treat an empty '0x' as invalid input early — the library requires at least one hex digit
When it happens
Trigger: input_type('0xzz12') or ruby sha256.rb 0xg1 (non-hex letters); input_type('0x') (empty payload fails the one-or-more rule); '0x0xff' (prefix doubled by concatenation); '0x1a 2b' (space). Plain text meant as a string that begins with 0x, for example hashing '0xprotocol' as ASCII, is caught too. Beware a trailing newline: it slips past this regex (the $ anchor matches before a final newline) and instead raises ArgumentError later inside pack('H*').
Common situations: Gluing strings together and doubling the 0x prefix ('0x' + '0xff'); copy-pasting hex that gained a space or was trimmed down to empty; command substitution leaving a trailing newline; intending ASCII text that starts with 0x.
Related errors
- Invalid binary string: #{input}
- Invalid input to hash256.rb. Expecting even number of hex ch
- We only operate on 32-bit words in SHA-256. Your x is #{ARGV
- (bitstring is not an exact amount of bytes)
AI-assisted analysis of in3rsha/sha256-animation@871e976d69 (2026-08-23).
Data as JSON: /api/errors/b36a81f897756465.
Report an issue: GitHub.