Skip to content

positional_too_many

More positional children than a (head-set …) ceiling allows: the head’s :max, or the set’s :max-children.

A (head-set …) says which heads a positional slot accepts. A (head …) entry inside one can also say how many:

(value-kind :name pipeline-section :underlying form
:heads (head-set
(head :name vertex :min 1 :max 1)
(head :name fragment :max 1)
(head :name constant)))

vertex exactly once, fragment at most once, constant any number of times. A second (fragment …) under a form whose :positional is that kind reports here.

The diagnostic lands on the child that crosses the ceiling, not on the parent, so the squiggle is on the line to delete. You get one per form regardless of how far over you went, since the crossing child names the real count, so the message stays honest without repeating itself down the rest of the list.

Two ways to fix it, and which one is right depends on what you meant. Delete or merge the extra child, if the duplicate was a mistake. Or raise the bound in the manifest, if the schema was stricter than the domain.

:open true does not silence this. Openness widens which keywords a form accepts; it says nothing about its positional children, and the neighbouring positional rules (not_head_member, duplicate_positional_flag) fire on open forms too.

Bounds count only at a form’s :positional slot. The same kind reused on a (key …) slot or as a vector-shape :element carries them inertly: a keyed slot holds one value, and a vector element is a value rather than a child list.

The set has a ceiling too. :max-children on the (head-set …) itself counts children of any head in the set:

(value-kind :name bgl-resource :underlying form
:heads (head-set :min-children 1 :max-children 1
(head :name buffer :max 1)
(head :name sampler :max 1)
(head :name texture :max 1)))

“exactly one resource, and not two of the same”. The per-head :max 1s cannot say the first part: one buffer and one sampler satisfies all three of them. If the message names a bracketed set (at most 1 positional child from [buffer | sampler | texture]) rather than one head, this is the level that fired.

When both levels would fire on one child (a second (buffer …) under the kind above crosses buffer’s ceiling and the set’s) only the per-head one is reported. It names the line to delete, and the set’s claim follows from it. So a set-level message means the children are individually fine and there are simply too many of them together, which is a different repair: pick one, rather than de-duplicate.


Run sjon explain positional_too_many to read this at a terminal, browse every code, or work through diagnostics-driven repair if you want the habit rather than the answer.