kestra-io/kestra · error · PebbleException

Need a string to hash

Error message

Need a string to hash

What it means

Thrown by the SHA filter family (sha1, sha256, etc.) when the input to the filter is not a String. MessageDigest operates on bytes, and the filter only accepts String inputs (encoded as UTF-8); any other type (Number, Boolean, Map, List, custom object) is rejected up front with the actual class in the message.

Source

Thrown at core/src/main/java/io/kestra/core/runners/pebble/filters/ShaBaseFilter.java:41

    }

    @Override
    public Object apply(Object input, Map<String, Object> args, PebbleTemplate self,
        EvaluationContext context, int lineNumber) throws PebbleException {
        if (input == null) {
            return null;
        }

        if (input instanceof String str) {
            try {
                MessageDigest digest = MessageDigest.getInstance(algorithm);
                byte[] encodedHash = digest.digest((str).getBytes(StandardCharsets.UTF_8));
                return bytesToHex(encodedHash);
            } catch (Exception e) {
                throw new PebbleException(e, "Hashing exception encountered\n", lineNumber, self.getName());
            }
        } else {
            throw new PebbleException(null, "Need a string to hash\n", lineNumber, self.getName());
        }
    }

    private static String bytesToHex(byte[] bytes) {
        StringBuilder hexString = new StringBuilder(2 * bytes.length);
        for (byte aByte : bytes) {
            String hex = Integer.toHexString(0xff & aByte);
            if (hex.length() == 1) {
                hexString.append('0');
            }
            hexString.append(hex);
        }
        return hexString.toString();
    }

}

View on GitHub (pinned to 823fada927)

Solutions

  1. Stringify before hashing: `{{ myval | toString | sha256 }}` (or rely on string interpolation `{{ myval ~ "" | sha256 }}` if appropriate).
  2. For JSON content, serialize explicitly before hashing.
  3. Check the upstream output type and adjust the filter chain.

Example fix

# before
{{ outputs.gen.id | sha256 }}
# after
{{ outputs.gen.id | toString | sha256 }}
Defensive patterns

Strategy: type-guard

Validate before calling

# Stringify non-string inputs before hashing:
{% if myval is string %}
  {{ myval | sha256 }}
{% else %}
  {{ myval | toString | sha256 }}
{% endif %}

Type guard

# Pebble: `is string` narrows to the accepted type.
# Use `is number`/`is iterable` to branch other shapes before hashing.

Prevention

When it happens

Trigger: Calling `{{ 42 | sha256 }}`, `{{ someMap | sha256 }}`, or `{{ outputs.task.value | sha256 }}` where the value is a non-String type. Commonly happens when an upstream output is already typed (INTEGER/JSON object) rather than a string.

Common situations: Hashing a numeric ID without first stringifying; hashing a JSON object by accident (user intended to hash its serialized form).

Related errors


AI-assisted analysis of kestra-io/kestra@823fada927 (2026-08-14). Data as JSON: /api/errors/b08151378158bfcc. Report an issue: GitHub.