Homepage

Multiline tags for all tags, JSON literal arguments for tags and filters, Liquid error stack traces, safer WebSocket subscriptions, upgraded file upload library

NEW

  • Multiline tag syntax: Liquid tags can now span multiple lines, so long or deeply nested arguments can be formatted for readability instead of being crammed onto a single line. This works for tags across the board (assign, function, include, background, etc.), for example:

{% function result = 'lib/create_order',
   customer_id: customer.id,
   items: [
     { "sku": "ABC", "qty": 2 },
     { "sku": "XYZ", "qty": 1 }
   ],
   note: "priority" %}

  • JSON literal arguments: JSON object and array literals - including nested structures, variables as values, and string interpolation - can now be passed directly as arguments to tags and filters, without first building them up with assign or parse_json, for example:

{% include 'shared/card', data: { "title": "Hello", "tags": ["news", "featured"], "active": true } %}

{% function total = 'lib/sum', numbers: [1, 2, 3] %}

{% assign items = value | default: [] %}

IMPROVED

  • Better error handling with stack traces: Errors raised while rendering Liquid now include a stack trace pointing at the file and line where the error occurred, instead of only a top-level message. The trace is captured through the same mechanism as the log tag, making it much easier to locate the source of a problem in your logs.

  • More reliable and secure WebSocket subscriptions: Subscribing to a WebSocket channel now always resolves to an explicit verdict. Previously, an error raised while evaluating a subscription could bubble up and leave the client with no confirmation frame at all, causing it to resubscribe indefinitely. Now every rejected subscribe attempt receives a structured subscription_error message (delivered right before the reject_subscription frame) carrying:

    • a stable, machine-readable code (unauthorized, instance_not_found, subscribed_partial_error, or internal) that your client can switch on,
    • a human-readable message, and
    • a retryable boolean telling the client whether resubscribing later may help.

    Because the reject_subscription frame cannot carry a payload, the client should read this message in its received(data) handler and correlate it by subscription identifier - the rejected() callback receives no arguments. Messages sent to the client are always generic (no internal detail is leaked over the socket); a Liquid error raised inside your channel's subscribed partial is instead written to the error log under the WebSocketSubscribeError code, so you can debug it from the admin.

  • New websockets_require_subscribed_partial feature flag: This new app/config.yml flag makes WebSocket channel authorization fail-closed - a channel with no channels/<name>/subscribed partial rejects every subscription instead of falling back to the legacy open default that admits any same-origin subscriber. It defaults to true (secure by default); set websockets_require_subscribed_partial: false in your config.yml to keep the legacy open behaviour. Regardless of this flag, a cross-origin connection without an authorizing subscribed partial is always rejected.

  • Upgraded internal file upload library: The underlying library that handles file uploads and processing (powering user uploads and image versions) has been upgraded to its latest version. This brings upstream security patches, bug fixes, and performance improvements. No changes are required in your application - uploads continue to work exactly as before.

Questions?

We are always happy to help with any questions you may have.

contact us