Manual:Template limits
The MediaWiki software several parameters that limit the complexity of a page, and the amount of data that can be included. These limits mainly concern data that is transcluded or substituted during expansion of a page, as opposed to data directly in the source of the page itself. This page explains how and why these limits are applied, and how users can work within the limits.
Background
editWhat is this about?
editThe MediaWiki parser uses a "preprocessor" which converts the wikitext into a data structure known as an XML tree, and then uses this tree to produce "expanded" wikitext, where double- and triple-braced structures are replaced by their result.
During the conversion process, the software uses several counters to track the complexity of the page that is being generated. When the parsing of a page begins, these counters are set to zero, but they are incremented during the parsing process, as described below. There are upper limits on these counters, and the parser does not allow these limits to be exceeded.
Why are there limits?
editVery long or complicated pages are slow to parse. Not only is this an inconvenience for users, but it can also be used to mount a denial of service (DoS) attack on the servers, in which a page request forces the MediaWiki software to parse an unreasonably large quantity of data. The limits help to prevent this kind of attack, and ensure that pages are rendered in a reasonable time. (Nevertheless, sometimes a complex page within the limits gives a time-out error; this depends on how busy the servers are.)
Working within the limits
editWhen a page reaches the template limits, the most common solution is to make the templates shorter, using methods described below. If this isn't possible, it may be necessary to include more data directly in the page source, rather than transcluding it from templates (e.g., formatting references by hand or using <references />
instead of {{Reflist }}). On the other hand, a template can help the server avoid doing duplicate work, see below.
When do problems arise?
editThe inclusion limits are most commonly reached on pages that use the same template many times, for example using one transclusion per row of a long table. Even though the amount of data that the template adds to the final page may be small, it is counted each time the template is used, and so the limit may be encountered sooner than expected. Pages that only include a few dozen templates are unlikely to exceed the inclusion limits, unless these templates themselves include a lot of data.
How can you find out?
editOnce the page body is processed, an HTML comment is added towards the end of the HTML code of the page with the final values of the various counters. For example, the page HIV/AIDS (on January 1, 2024) contains the following comment in its generated HTML source:
<!--
NewPP limit report
Parsed by mw1416
Cached time: 20231227101515
Cache expiry: 2592000
Reduced expiry: false
Complications: [vary‐revision‐sha1, show‐toc]
CPU time usage: 2.767 seconds
Real time usage: 3.151 seconds
Preprocessor visited node count: 20971/1000000
Post‐expand include size: 928915/2097152 bytes
Template argument size: 9264/2097152 bytes
Highest expansion depth: 15/100
Expensive parser function count: 51/500
Unstrip recursion depth: 1/20
Unstrip post‐expand size: 1121339/5000000 bytes
Lua time usage: 1.705/10.000 seconds
Lua memory usage: 10566120/52428800 bytes
Lua Profile:
MediaWiki\Extension\Scribunto\Engines\LuaSandbox\LuaSandboxCallback::preprocess 180 ms 10.6%
? 160 ms 9.4%
MediaWiki\Extension\Scribunto\Engines\LuaSandbox\LuaSandboxCallback::callParserFunction 140 ms 8.2%
MediaWiki\Extension\Scribunto\Engines\LuaSandbox\LuaSandboxCallback::plain 140 ms 8.2%
MediaWiki\Extension\Scribunto\Engines\LuaSandbox\LuaSandboxCallback::gsub 80 ms 4.7%
MediaWiki\Extension\Scribunto\Engines\LuaSandbox\LuaSandboxCallback::find 80 ms 4.7%
dataWrapper <mw.lua:672> 80 ms 4.7%
select_one <Module:Citation/CS1/Utilities:426> 80 ms 4.7%
recursiveClone <mwInit.lua:41> 80 ms 4.7%
<mwInit.lua:41> 60 ms 3.5%
[others] 620 ms 36.5%
Number of Wikibase entities loaded: 0/400
-->
(Some items may not be present, depending on which extensions they have installed; for example, the "Lua" items are added by Extension:Scribunto.)
Because of the way the counters are increased, the preprocessor visited node count, post-expand include size, and template argument size will usually be less than their limits. If any of these items are close to their limit, then it is likely that some of the templates have not been expanded. Each occurrence of an unexpanded template is identified in the page body by an HTML comment containing an error message.
Click "Parser profiling data" at the bottom of a preview to see similar data for the preview without saving it.
Expansion
editTemplates in non-executed branches of conditional parser functions are not expanded, and therefore not counted. For example, in the code {{#if:yes|{{bar}}|{{foo}}}}
, the template {{bar}}
is expanded, but the template {{foo}}
is not expanded.
Nevertheless, it is possible for a template argument to contribute to the counts even though it does not appear in the final output. For example, if the code {{#if:{{foo}}|yes|no}}
is parsed, the length of the expanded version of template {{foo}}
will be added to the post-expand counter, because that template must be expanded to decide which branch of the conditional should be selected.
Preprocessor node count
editThe preprocessor node count measures the complexity of the page (not the volume of data). As the parser is expanding a page, it creates a data structure known as a tree that corresponds to the HTML structure of the page. Each node of the tree that is visited during expansion is counted towards the preprocessor node count. If this count is exceeded, the parser will abort parsing with the error "Node-count limit exceeded" visible in the generated HTML.
The count starts with 1 for plain text. A pair of nowiki tags counts for 3, a header for 2, etc. A link does not contribute to the count. For the expansion of #switch
every checked condition adds 2 to the count. In the case of multiple expansions of the same template the content of a template without arguments counts only once, but that of a template with arguments (even if constant) counts multiple times. In contrast to this, the result of an expansion can be used multiple times while counting only once if it is assigned to a template parameter, and that template has multiple uses of this parameter.
Pages exceeding this limit are automatically categorized into Category:Pages where node count is exceeded.
Post-expand include size
editThe post-expand include size is the sum of the lengths of the expanded wikitexts generated by templates, parser functions and variables. Whenever the parser is instructed by the source code of a page to expand a template etc. (that is, to replace it by transclusion or substitution), the parser adds together the length of the expanded wikitext generated by the template etc. and the current counter value of the page. If this sum is more than the post-expand limit (same as the max article size limit), the initial template etc. is not replaced and an error message is added as a comment in the output HTML. Otherwise the post-expand counter is increased to the new value, and parsing continues. A template that is expanded more than once in the page contributes more than once to its post-expand include size.
Template invocations with no arguments have an expanded text cache. So if {{foo}}
includes the second-level meta-template {{bar}}
, then multiple invocations of {{foo}}
will only increment the post-expand include size for the fully-expanded {{foo}}
; the secondary include {{bar}}
is only counted once. But if you included the same template multiple times with {{foo|arg}}
, then the secondary templates are counted each time, even if the argument is the same.
Pages exceeding the post-expand include size limit are automatically added to Category:Pages where template include size is exceeded
Using comments, noinclude and onlyinclude
editOnly data that survives the preprocessor expansion stage is counted towards the post-expand counter. The length of HTML comments in the wikitext (which are not reproduced in the HTML source produced) is not included in the post-expand counter. Code which is either inside a <noinclude> section or outside an <onlyinclude> section does not get expanded, so these sections do not contribute to the post-expand size. This also means that category tags only contribute if they are included (to categorize pages calling the template).
Nested transclusions
editNote that the sizes of the wikitexts of all expanded templates and parser functions are added, even in the case of nesting (see phab:T15260), so extra levels increase the count. If page A transcludes B and B does nothing but transclude C, then the size of C will be counted twice towards the post-expand include size on page A, and similarly if a template consists of a parser function call, or a parser function has a template call as parameter, etc. Possible substitutions to reduce nesting include:
{{#if:{{{test|}}}|{{template1}}|{{template2}} }}
replaced with{{ {{#if:{{{test|}}}|template1|template2}} }}
.
Non-rendered transclusions
editNon-rendered tranclusions still count towards limit. For example, a page which contains only {{#if:{{:Main Page}}}}
would still have a post-expand include size even though it would have no output at all.
The same applies to Scribunto modules. For example, {{#invoke:Test|main}}
would still increase post-expand include size even if Module:Test were simply:
mw.getCurrentFrame():preprocess'{{msgnw::Main Page}}' -- remove this line and post-expand include size becomes zero
return { main = function() end } -- p.main() has no return value
Template argument size
editThe template argument size counter keeps track of the total length of template arguments that have been substituted. Its limit is the same as the article size limit.
Example:
{{3x|{{2x|abcde}}}}
has a template argument size of 40 bytes: the argument abcdeabcde
is counted 3 times, the argument abcde
twice.
Arguments in the template call which do not match any parameter tag in the template do not count.
If a template contains a switch, use of template arguments beyond a match do not count. Up to and including the matching case, template arguments used on the left of the equals signs count twice. Those on the right of the equals sign count for the matching case only.
Pages exceeding the template argument size limit are automatically added to Category:Pages containing omitted template arguments
Highest expansion depth
editThe parser defines a maximum expansion depth of $wgMaxTemplateDepth
, defaulting to 100 in MediaWiki 1.38 or later, or 40 in earlier versions. Each template call generally takes up two depth slots (one for the template, one for its parameter) whereas each parser function call generally takes up one. So the following fails:
0 {{1x| 1 {{1x| 2 {{1x| 3 {{1x| 4 {{1x| 5 {{1x| 6 {{1x| 7 {{1x| 8 {{1x| 9 {{1x| 10 {{1x| 11 {{1x| 12 {{1x| 13 {{1x| 14 {{1x| 15 {{1x| 16 {{1x| 17 {{1x| 18 {{1x| 19 {{1x| 20 {{1x| 21 {{1x| 22 {{1x| 23 {{1x| 24 {{1x| 25 {{1x| 26 {{1x| 27 {{1x| 28 {{1x| 29 {{1x| 30 {{1x| 31 {{1x| 32 {{1x| 33 {{1x| 34 {{1x| 35 {{1x| 36 {{1x| 37 {{1x| 38 {{1x| 39 {{1x| 40 {{1x| 41 {{1x| 42 {{1x| 43 {{1x| 44 {{1x| 45 {{1x| 46 {{1x| 47 {{1x| 48 {{1x| 49 {{1x|50 {{tc}} 50}} 49}} 48}} 47}} 46}} 45}} 44}} 43}} 42}} 41}} 40}} 39}} 38}} 37}} 36}} 35}} 34}} 33}} 32}} 31}} 30}} 29}} 28}} 27}} 26}} 25}} 24}} 23}} 22}} 21}} 20}} 19}} 18}} 17}} 16}} 15}} 14}} 13}} 12}} 11}} 10}} 9}} 8}} 7}} 6}} 5}} 4}} 3}} 2}} 1}} 0
gives: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 {{Expansion depth limit exceeded}} 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
Whereas the following works:
0 {{#if:x| 1 {{#if:x| 2 {{#if:x| 3 {{#if:x| 4 {{#if:x| 5 {{#if:x| 6 {{#if:x| 7 {{#if:x| 8 {{#if:x| 9 {{#if:x| 10 {{#if:x| 11 {{#if:x| 12 {{#if:x| 13 {{#if:x| 14 {{#if:x| 15 {{#if:x| 16 {{#if:x| 17 {{#if:x| 18 {{#if:x| 19 {{#if:x| 20 {{#if:x| 21 {{#if:x| 22 {{#if:x| 23 {{#if:x| 24 {{#if:x| 25 {{#if:x| 26 {{#if:x| 27 {{#if:x| 28 {{#if:x| 29 {{#if:x| 30 {{#if:x| 31 {{#if:x| 32 {{#if:x| 33 {{#if:x| 34 {{#if:x| 35 {{#if:x| 36 {{#if:x| 37 {{#if:x| 38 {{#if:x| 39 {{#if:x| 40 {{#if:x| 41 {{#if:x| 42 {{#if:x| 43 {{#if:x| 44 {{#if:x| 45 {{#if:x| 46 {{#if:x| 47 {{#if:x| 48 {{#if:x| 49 {{#if:x|50 {{tc}} 50}} 49}} 48}} 47}} 46}} 45}} 44}} 43}} 42}} 41}} 40}} 39}} 38}} 37}} 36}} 35}} 34}} 33}} 32}} 31}} 30}} 29}} 28}} 27}} 26}} 25}} 24}} 23}} 22}} 21}} 20}} 19}} 18}} 17}} 16}} 15}} 14}} 13}} 12}} 11}} 10}} 9}} 8}} 7}} 6}} 5}} 4}} 3}} 2}} 1}} 0
gives: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 in 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
(the above would fail if it were to be extended to 100 levels of nested if statements)
Pages exceeding this limit are automatically categorized into Category:Pages where expansion depth is exceeded
Expensive parser function calls
editThere is a limit of 500 to the expensive parser function count, i.e., the number of calls of expensive parser functions, which are:
- #ifexist – branching depending on whether a particular page exists. If the limit on this counter is exceeded, additional #ifexist calls will act as though the pages they query do not exist.
- PAGESINCATEGORY or PAGESINCAT
- PAGESIZE
- CASCADINGSOURCES
- REVISIONUSER, when used on a page other than the current page
- REVISIONTIMESTAMP, when used on a page other than the current page
- Some Lua functions, many equivalent to other items in this list:
- mw.site.stats.pagesInCategory
- Some title object properties and methods
<syntaxhighlight>...</syntaxhighlight>
tags
It is also possible to manually increment the expensive parser function count from a Lua module by using mw.incrementExpensiveFunctionCount.
Pages that exceed this limit are automatically categorized into Category:Pages with too many expensive parser function calls (recent additions).
See also: Manual:$wgExpensiveParserFunctionLimit
Unstrip post-expand size
editThe unstrip post-expand size counter tracks the total bytes added via TemplateStyles and some other extensions implemented in a similar manner (the tag itself is counted towards the post-expand include size count).
#time
editThe total length of the format strings of function #time
is limited to 6000 characters [1]. The error message is given by MediaWiki:Pfunc time too long). For each combination of the expanded wikitext of a format string and the expanded wikitext of an expression for the time (e.g. "1 Mar 2008 -1day"), repeated use is not counted, as the results are cached.
Unfortunately, the count is not in the limit report.