octobercms/october · error · ApplicationException
The markup filter/function for '{$this->name}' is not callab
Error message
The markup filter/function for '{$this->name}' is not callable. What it means
MarkupExtensionItem wraps a Twig filter or function registered through a plugin's registerMarkupTags() (or CMS markup extensions). getTwigCallback() is called when the item is bound into Twig; for non-wildcard names it checks the stored callback with is_callable() and throws ApplicationException naming the filter/function when the callback cannot actually be invoked. Wildcard registrations (e.g. 'str_*' routing to Str::*) bypass this check and resolve dynamically.
Source
Thrown at modules/system/classes/MarkupExtensionItem.php:170
/**
* getTwigCallback returns a callback function suitable for Twig
*/
public function getTwigCallback()
{
// Handle a wildcard function
if (strpos($this->name, '*') !== false && $this->isWildCallable()) {
return function ($name) {
$arguments = array_slice(func_get_args(), 1);
$method = $this->getWildCallback(Str::camel($name));
return $method(...$arguments);
};
}
// Cannot call item method
$callable = $this->callback;
if (!is_callable($callable)) {
throw new ApplicationException("The markup filter/function for '{$this->name}' is not callable.");
}
// Wrap in a closure to prevent Twig from reflecting facades
// when applying its named closure support
return function(...$args) use ($callable) {
return $callable(...$args);
};
}
/**
* getTwigOptions returns options passed to the Twig definition
*/
public function getTwigOptions(): array
{
return ($this->escapeOutput ? [] : ['is_safe' => ['html']]) + $this->options;
}
/**View on GitHub (pinned to b608633a7e)
Solutions
- Fix the callable: use [MyHelper::class, 'method'], a namespaced function string like 'strtoupper', or a closure.
- Verify the method exists, is public (and static if called statically), and the class is autoloaded with the correct namespace.
- Replace 'Class@method' strings with the array form — PHP's is_callable() rejects them.
- Sanity-check with is_callable($callback) right after registering before reloading the frontend.
Example fix
// before
public function registerMarkupTags()
{
return ['filters' => ['excerpt' => 'Acme\Blog\Classes\Excerpt@make']];
}
// after
public function registerMarkupTags()
{
return ['filters' => ['excerpt' => [\Acme\Blog\Classes\Excerpt::class, 'make']]];
} Defensive patterns
Strategy: type-guard
Validate before calling
// Validate registerMarkupTags() output before returning it
public function registerMarkupTags()
{
$tags = ['filters' => ['excerpt' => [Excerpt::class, 'make']]];
foreach ($tags['filters'] ?? [] as $name => $callback) {
if (!is_callable($callback)) {
throw new RuntimeException("Markup filter '{$name}' callback is not callable.");
}
}
return $tags;
} Type guard
function isMarkupCallbackValid($callback): bool
{
if (is_string($callback) && strpos($callback, '@') !== false) {
return false; // 'Class@method' form is never callable in PHP
}
return is_callable($callback);
} Prevention
- Use [Class::class, 'method'] or closures for markup callbacks; never 'Class@method' strings.
- Test plugin boot plus one template render in CI so a bad callback fails the build, not production.
- After renaming helper classes, grep registerMarkupTags() implementations for stale references.
When it happens
Trigger: registerMarkupTags() returning ['filters' => ['excerpt' => 'acme_excerpt']] where that function does not exist; ['functions' => ['tweet' => ['Acme\Blog\Classes\Twitter', 'send']]] where send is not a public static method or the class name has a typo; callbacks written in 'Class@method' string form, which PHP does not treat as callable; referencing a class that is not autoloadable at registration time.
Common situations: First render of a page/template after adding a new markup tag; renaming a helper class without updating registerMarkupTags(); plugin authors copying the 'Class@method' convention from Laravel-ish contexts where October requires [Class::class, 'method'] or a closure; definitions supplied via YAML/JSON where the callable string was mangled.
Related errors
- Error parsing the ${name} attribute value. ${e}
- Error parsing the data-chart-options attribute value. ${e}
- Error parsing Inspector field values. ${err}
- Error parsing Inspector configuration. ${err}
- ${errorMessage} Property: ${this.propertyDefinition.property
AI-assisted analysis of octobercms/october@b608633a7e (2026-08-21).
Data as JSON: /api/errors/8dae9126b88f1bef.
Report an issue: GitHub.