Shopify/liquid · error · Liquid::ArgumentError
invalid base64 provided to base64_url_safe_decode
Error message
invalid base64 provided to base64_url_safe_decode
What it means
The base64_url_safe_decode Liquid filter raises Liquid::ArgumentError when Base64.urlsafe_decode64 cannot decode the input — typically because it contains standard-alphabet characters (+ and /) or is malformed (bad padding/length).
Solutions
- Use base64_decode for standard base64 strings containing + or /
- Ensure the input uses - and _ alphabet characters with correct padding
- Validate the string length and alphabet before decoding
Example fix
<!-- before -->
{{ 'a+b/c==' | base64_url_safe_decode }}
<!-- after -->
{{ 'a-b_c==' | base64_url_safe_decode }} Defensive patterns
Strategy: validation
Validate before calling
def urlsafe_base64?(s)
s.is_a?(String) && s.match?(/\A[A-Za-z0-9_-]*={0,2}\z/) && (s.length % 4).zero?
end Type guard
def urlsafe_alphabet?(v) v.is_a?(String) && !v.match?(/[+\/]/) end
Try / catch
begin
output = Liquid::Template.parse(tpl).render(assigns)
rescue Liquid::ArgumentError => e
raise unless e.message.include?('base64_url_safe_decode')
# retry with base64_decode for standard alphabet input
end Prevention
- Match the filter to the base64 alphabet used by the producer
- Validate alphabet/padding before filtering
- Test with tokens from real API payloads
When it happens
Trigger: Calling {{ 'a+b/c==' | base64_url_safe_decode }} with standard base64 containing + or /, or a string with invalid length/padding for URL-safe decoding.
Common situations: Feeding standard base64 (from JWT segments or API responses using + /) into the URL-safe filter; truncated tokens; padding mixed with URL-safe unpadded encoding.
Related errors
- invalid base64 provided to base64_decode
- invalid byte sequence in #
- concat filter requires an array argument
- Invalid byte sequence in #
- unsafe parse_expression cannot be used in strict2 mode
AI-assisted analysis of Shopify/liquid@807d45a6b3 (2026-09-08).
Data as JSON: /api/errors/0e7fdc4d42f29c11.
Report an issue: GitHub.
Appendix: source
Thrown at lib/liquid/standardfilters.rb:202
# Encodes a string to URL-safe [Base64 format](https://developer.mozilla.org/en-US/docs/Glossary/Base64).
# @liquid_syntax string | base64_url_safe_encode
# @liquid_return [string]
def base64_url_safe_encode(input)
Base64.urlsafe_encode64(Utils.to_s(input))
end
# @liquid_public_docs
# @liquid_type filter
# @liquid_category string
# @liquid_summary
# Decodes a string in URL-safe [Base64 format](https://developer.mozilla.org/en-US/docs/Glossary/Base64).
# @liquid_syntax string | base64_url_safe_decode
# @liquid_return [string]
def base64_url_safe_decode(input)
input = Utils.to_s(input)
StandardFilters.try_coerce_encoding(Base64.urlsafe_decode64(input), encoding: input.encoding)
rescue ::ArgumentError
raise Liquid::ArgumentError, "invalid base64 provided to base64_url_safe_decode"
end
# @liquid_public_docs
# @liquid_type filter
# @liquid_category string
# @liquid_summary
# Returns a substring or series of array items, starting at a given 0-based index.
# @liquid_description
# By default, the substring has a length of one character, and the array series has one array item. However, you can
# provide a second parameter to specify the number of characters or array items.
# @liquid_syntax string | slice
# @liquid_return [string]
def slice(input, offset, length = nil)
offset = Utils.to_integer(offset)
length = length ? Utils.to_integer(length) : 1
begin
if input.is_a?(Array)View on GitHub (pinned to 807d45a6b3)