twigphp/Twig · error · Twig\Error\RuntimeError
Only empty strings may be passed as string arguments to…
Error message
Only empty strings may be passed as string arguments to html_attr_merge. This is to support the implicit else clause for ternary operators.
What it means
html_attr_merge() merges attribute arrays but forbids non-empty string arguments. Empty strings are allowed only to support Twig's implicit ternary else clause (cond ? attrs : ''); any other string would be ambiguous and is rejected.
Solutions
- Convert the string to an associative array first, e.g. ['class' => 'foo'].
- Only pass '' (empty string) or arrays/false/null to the merge.
- Check each merge operand is_array($x) || '' === $x || null === $x || false === $x before calling.
Example fix
// before html_attr_merge(['class' => 'a'], 'id=main') // after html_attr_merge(['class' => 'a'], ['id' => 'main'])
Defensive patterns
Strategy: validation
Validate before calling
foreach ($operands as $op) { if (!is_array($op) && '' !== $op && null !== $op && false !== $op) throw new \TypeError('html_attr_merge operands must be arrays or empty strings'); } Type guard
function isMergeOperand(mixed $v): bool { return is_array($v) || '' === $v || null === $v || false === $v; } Try / catch
try { $attrs = html_attr_merge($base, $extra); } catch (Twig\Error\RuntimeError $e) { $attrs = $base; } Prevention
- Never pass raw attribute strings; always build arrays
- Remember '' is only valid as a ternary else placeholder
- Normalize operands with array_map cast helpers
When it happens
Trigger: Calling twig_html_attr_merge() with a non-empty string argument, e.g. merging an array with 'foo=bar' instead of ['foo' => 'bar'].
Common situations: Trying to merge a raw attribute string with an array; a ternary branch accidentally returning a string instead of an array; passing query-string-like text expecting it to be parsed.
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 " " attribute value should be a scalar, an iterable, or…
- InlineStyle can only be created from iterable values.
- Attributes using InlineStyle can only be merged with…
- Only iterable values can be appended to InlineStyle.
- SeparatedTokenList can only be constructed from iterable or…
AI-assisted analysis of twigphp/Twig@a414c3a491 (2026-09-13).
Data as JSON: /api/errors/a5797a22ef82e6f3.
Report an issue: GitHub.
Appendix: source
Thrown at extra/html-extra/HtmlExtension.php:160
'sst' => new SeparatedTokenList($value, ' '),
'cst' => new SeparatedTokenList($value, ', '),
'style' => new InlineStyle($value),
default => throw new RuntimeError(\sprintf('Unknown attribute type "%s" The only supported types are "sst", "cst" and "style".', $type)),
};
}
/** @internal */
public static function htmlAttrMerge(iterable|string|false|null ...$arrays): array
{
$result = [];
foreach ($arrays as $array) {
if (!$array) {
continue;
}
if (\is_string($array)) {
throw new RuntimeError('Only empty strings may be passed as string arguments to html_attr_merge. This is to support the implicit else clause for ternary operators.');
}
foreach ($array as $key => $value) {
if (!isset($result[$key])) {
$result[$key] = $value;
continue;
}
$existing = $result[$key];
switch (true) {
case $value instanceof MergeableInterface:
$result[$key] = $value->mergeInto($existing);
break;
case $existing instanceof MergeableInterface:
$result[$key] = $existing->appendFrom($value);
break;View on GitHub (pinned to a414c3a491)