twigphp/Twig · error · Twig\Error\RuntimeError
Cannot merge incompatible values for key
Error message
Cannot merge incompatible values for key "%s".
What it means
When html_attr_merge() combines two attribute arrays under the same key, it can only merge array+array (union) or replace scalar+scalar / object+scalar combinations. Any other pairing (e.g. array vs scalar, or two incompatible AttributeValueInterface objects) falls to the default arm and throws this RuntimeError.
Solutions
- Make the shapes consistent: wrap scalars in arrays (['class' => ['a']] instead of ['class' => 'a']).
- Pre-normalize both arrays so each key has the same type before merging.
- Drop or rename one of the conflicting keys if they are semantically different.
- Catch the RuntimeError and fall back to one operand.
Example fix
// before html_attr_merge(['class' => ['a', 'b']], ['class' => 'c']) // after html_attr_merge(['class' => ['a', 'b']], ['class' => ['c']])
Defensive patterns
Strategy: validation
Validate before calling
foreach ($extra as $k => $v) { if (isset($base[$k]) && ((is_array($base[$k]) xor is_array($v)))) { $v = is_array($v) ? $v : [$v]; $base[$k] = is_array($base[$k]) ? $base[$k] : [$base[$k]]; } } Type guard
function areMergeable(mixed $a, mixed $b): bool { return (is_array($a) && is_array($b)) || (!is_array($a) && !is_array($b)); } Try / catch
try { $attrs = html_attr_merge($base, $override); } catch (Twig\Error\RuntimeError $e) { $attrs = array_merge($base, $override); } Prevention
- Keep a consistent shape per attribute key (always array or always scalar)
- Wrap scalars in arrays when merging list-like attributes
- Centralize attribute defaults in one builder function
When it happens
Trigger: Merging two arrays where the same key has an array value in one and a scalar in the other, e.g. ['class' => ['a','b']] merged with ['class' => 'a'].
Common situations: Combining default attributes with user-supplied overrides where a key changed shape between versions; conditional Twig expressions giving different shapes per branch.
Understand the failure class
Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.
Related errors
- Unknown attribute type
- Only empty strings may be passed as string arguments to…
- The " " attribute value cannot be JSON encoded.
- The " " attribute value should be a scalar, an iterable, or…
- Unknown " " configuration.
AI-assisted analysis of twigphp/Twig@a414c3a491 (2026-09-13).
Data as JSON: /api/errors/eac7909365cab766.
Report an issue: GitHub.
Appendix: source
Thrown at extra/html-extra/HtmlExtension.php:186
}
$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;
case is_iterable($existing) && is_iterable($value):
$result[$key] = [...$existing, ...$value];
break;
case (\is_scalar($existing) || \is_object($existing)) && (\is_scalar($value) || \is_object($value)):
$result[$key] = $value;
break;
default:
throw new RuntimeError(\sprintf('Cannot merge incompatible values for key "%s".', $key));
}
}
}
return $result;
}
/** @internal */
public static function htmlAttr(Environment $env, iterable|string|false|null ...$args): string
{
$attr = self::htmlAttrMerge(...$args);
$result = '';
$runtime = $env->getRuntime(EscaperRuntime::class);
foreach ($attr as $name => $value) {
if (null === $value = self::htmlAttrValue($name, $value)) {
continue;View on GitHub (pinned to a414c3a491)