twigphp/Twig · error · TypeError

Block chain templates must be strings or

Error message

Block chain templates must be strings or "%s" instances, "%s" given.

What it means

BlockChain's constructor accepts an iterable of templates, each either a string template name or a TemplateWrapper. If an element is neither (e.g. a raw Template object, null, or an array), a TypeError is thrown reporting the actual debug type via get_debug_type(). The chain needs wrappers it can unwrap and verify against the Environment.

Solutions

  1. Pass template name strings (they are loaded via $env->load internally) or TemplateWrapper instances from Environment::load().
  2. If you only have a Template, load its wrapper via the environment instead of passing the raw Template.
  3. Add a per-item check with instanceof TemplateWrapper before constructing the chain.

Example fix

// before
$chain = new \Twig\BlockChain($env, [$env->resolveTemplate('a.html.twig')]); // raw Template
// after
$chain = new \Twig\BlockChain($env, ['a.html.twig']); // or [$env->load('a.html.twig')]
Defensive patterns

Strategy: type-guard

Validate before calling

foreach ($templates as $t) {
    if (!is_string($t) && !$t instanceof \Twig\TemplateWrapper) {
        throw new \InvalidArgumentException(sprintf('Expected string or TemplateWrapper, got %s.', get_debug_type($t)));
    }
}

Type guard

function isChainTemplate(mixed $t): bool {
    return is_string($t) || $t instanceof \Twig\TemplateWrapper;
}

Try / catch

try {
    $chain = new \Twig\BlockChain($env, $templates);
} catch (\TypeError $e) {
    // normalize: map non-string entries through $env->load() or drop them
}

Prevention

When it happens

Trigger: Passing a \Twig\Template instance directly instead of a TemplateWrapper, passing null/false, or iterating a list that includes non-template values into Twig\BlockChain::__construct.

Common situations: Calling ->unwrap() yourself before passing to BlockChain, or mixing results from $env->resolveTemplate() (returns Template) with $env->load() (returns TemplateWrapper).

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


AI-assisted analysis of twigphp/Twig@a414c3a491 (2026-09-13). Data as JSON: /api/errors/517200b2f05f89c2. Report an issue: GitHub.

Appendix: source

Thrown at src/BlockChain.php:49

     * Whether the lineage can no longer move, making every further resolution pointless.
     */
    private bool $fixed = false;

    /**
     * @param iterable<string|TemplateWrapper> $templates Templates ordered from highest to lowest precedence
     * @param array<string, mixed>             $context   Default variables used to resolve dynamic parent expressions
     */
    public function __construct(
        private Environment $env,
        iterable $templates,
        private array $context = [],
    ) {
        foreach ($templates as $template) {
            if (\is_string($template)) {
                $template = $env->load($template);
            }
            if (!$template instanceof TemplateWrapper) {
                throw new \TypeError(\sprintf('Block chain templates must be strings or "%s" instances, "%s" given.', TemplateWrapper::class, get_debug_type($template)));
            }

            $template = $template->unwrap();
            if (!$template->isOwnedBy($env)) {
                throw new \LogicException('A block chain cannot contain templates from different Twig environments.');
            }

            $this->templates[] = $template;
        }

        if (!$this->templates) {
            throw new \InvalidArgumentException('A block chain requires at least one template.');
        }
    }

    /**
     * @param array<string, mixed> $context
     */

View on GitHub (pinned to a414c3a491)