twigphp/Twig · error · RuntimeError
Trimming side must be "left", "right" or "both".
Error message
Trimming side must be "left", "right" or "both".
What it means
Thrown by CoreExtension::trim when the `side` argument of Twig's `trim` filter is not one of 'left', 'right', or 'both'. The function uses a match expression and the default arm throws this RuntimeError for any other value. It protects users from silently getting no trimming when they misspell the side.
Solutions
- Use exactly one of 'left', 'right', or 'both' (lowercase) as the side argument
- If the side comes from a variable, normalize it first: side|lower, or default it with `side|default('both')`
- Check the calling template or custom code in the caller list (getValue, htmlAttr, stripCommonIndentation, testMarkdown, compare) for a wrong literal
- For dynamic values, validate in PHP before rendering or map unknown values to 'both'
Example fix
// before (Twig)
{{ ' hello '|trim(' ', 'Left') }}
// after
{{ ' hello '|trim(' ', 'left') }} Defensive patterns
Strategy: validation
Validate before calling
$side = \in_array($side, ['left', 'right', 'both'], true) ? $side : 'both';
Try / catch
try {
$out = $twig->render('t.html', ['side' => $side]);
} catch (\Twig\Error\RuntimeError $e) {
if (str_contains($e->getMessage(), 'Trimming side')) {
$out = $twig->render('t.html', ['side' => 'both']);
} else { throw $e; }
} Prevention
- Only pass the exact lowercase literals 'left', 'right', 'both'
- Normalize dynamic values with |lower and |default('both') in templates
- Map user/config input through a whitelist before rendering
- Review custom extensions (htmlAttr, compare, etc.) that call trim internally for correct literals
When it happens
Trigger: Using the `trim` filter in a Twig template with a `side` argument that is misspelled, mis-translated, dynamically computed, or of the wrong type, e.g. `{{ name|trim('', 'lft') }}`, `{{ name|trim('', 'LEFT') }}`, or `{{ name|trim('', side) }}` where side is 'None'/'centre'/etc.
Common situations: Typo in template ('both' vs 'bot', 'left' vs 'lft'); case-sensitivity mistakes ('Left'); passing a Twig variable computed from config that holds an unexpected value; upgrading code that previously used custom filter semantics.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- The "html_classes" function argument
- Failed to load Twig template
- The "cycle" function expects a non-empty sequence.
- The "random" function cannot pick from an empty sequence or…
- Regexp " " passed to "matches" failed: .
AI-assisted analysis of twigphp/Twig@a414c3a491 (2026-09-13).
Data as JSON: /api/errors/9d74e4d77726deff.
Report an issue: GitHub.
Appendix: source
Thrown at src/Extension/CoreExtension.php:1230
* @param string|\Stringable|null $string
* @param string|null $characterMask
* @param string $side left, right, or both
*
* @throws RuntimeError When an invalid trimming side is used
*
* @internal
*/
public static function trim($string, $characterMask = null, $side = 'both'): string|\Stringable
{
if (null === $characterMask) {
$characterMask = self::DEFAULT_TRIM_CHARS;
}
$trimmed = match ($side) {
'both' => trim($string ?? '', $characterMask),
'left' => ltrim($string ?? '', $characterMask),
'right' => rtrim($string ?? '', $characterMask),
default => throw new RuntimeError('Trimming side must be "left", "right" or "both".'),
};
// trimming a safe string with the default character mask always returns a safe string (independently of the context)
return $string instanceof Markup && self::DEFAULT_TRIM_CHARS === $characterMask ? new Markup($trimmed, $string->getCharset()) : $trimmed;
}
/**
* Inserts HTML line breaks before all newlines in a string.
*
* @param string|null $string
*
* @internal
*/
public static function nl2br($string): string
{
return nl2br($string ?? '');
}
View on GitHub (pinned to a414c3a491)