spine-rigc 2.57.0 → 2.58.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/docs/AUTHORING.md CHANGED
@@ -5,6 +5,11 @@ seen this repository and cannot see what it is authoring. Together with the
5
5
  validator's messages it *is* the interface: there is no editor viewport here, so
6
6
  the only way to know a rig is right is to compile it and read what comes back.
7
7
 
8
+ A compile refusal now ends with ` (see rigc guide <CODE>)`: run that command
9
+ first for its one repair row. For surrounding context, `rigc guide §5.1.<k>`
10
+ prints one numbered compile-error group, capped at 30,000 UTF-8 bytes. An uncoded
11
+ library error retains the legacy `§5.1` pointer.
12
+
8
13
  Two input files, one CLI loop, and a list of named failures. Everything below is
9
14
  checked against the code that implements it.
10
15
 
@@ -291,7 +296,8 @@ for `vote` (default `ballot.html`).
291
296
 
292
297
  `guide` reads this page rather than a rig: `rigc guide <RULE>` prints the row of §5
293
298
  (or of `docs/INGEST.md`'s finding-code table) for the rule a failure line names, and
294
- `rigc guide §<n>` one section — §5 says when to reach for it.
299
+ `rigc guide §<n>` its heading, own prose and subsection index; `--all` also prints
300
+ the subsections' bodies. A leaf prints its full text either way — §5 says when to reach for it.
295
301
 
296
302
  `skills install` is the other command that is not about a rig: it puts the agent
297
303
  skills the package ships where an agent host looks for them. Run it through the
@@ -6782,14 +6788,18 @@ Failures arrive in two layers, and they read differently.
6782
6788
  ` (see rigc guide <RULE>)` — a gate's `FAIL` line, a `vote --record` refusal and an
6783
6789
  `ingest` finding. `rigc guide <RULE>` prints that rule's row(s), each under the file,
6784
6790
  the section and the heading it sits in, read from the shipped guide when it runs;
6785
- `rigc guide §<n>` prints one section of this page and lists its subsections with their
6786
- sizes, `rigc guide §<n>.<m>` the m-th `###` under it and `rigc guide §<n>.<m>.<k>` the
6787
- k-th `####` under that — so a citation such as §4.5.1 here is a command. A name the
6791
+ `rigc guide §<n>` prints the section's heading, its own prose and an index of its
6792
+ subsections with their sizes. `rigc guide §<n> --all` also prints those subsections'
6793
+ bodies; a section without subsections prints its full text either way. The header
6794
+ and index sizes describe the full spans in this ledger, including subsection bodies.
6795
+ `rigc guide §<n>.<m>` addresses the m-th `###` under it and `rigc guide §<n>.<m>.<k>` the
6796
+ k-th `####` under that; both take `--all` too — so a citation such as §4.5.1 here is a command. A name the
6788
6797
  guide does not have is refused by a rule of its own — `GUIDE_RULE_KNOWN` with the
6789
6798
  three nearest real names, `GUIDE_SECTION_KNOWN` with the sections that do exist —
6790
- on stderr, exit 1 (§5.5). A compile error
6791
- names no rule — §5.1's tables are keyed on the message — so it ends with
6792
- ` (see rigc guide §5.1)`, the section its row is in.
6799
+ on stderr, exit 1 (§5.5). A compile error carries a stable `CE_` code and points
6800
+ at that code's one row in §5.1. Only a legacy uncoded library error ends with
6801
+ ` (see rigc guide §5.1)`. `--all` takes a section address; with a rule name it is
6802
+ a usage refusal, exit 2 — omit it to read the row.
6793
6803
 
6794
6804
  📥 **A third surface is `ingest`'s, and it is not a failure at all.** What a skeleton
6795
6805
  holds and the spec format cannot say is **recorded** rather than refused — one coded
@@ -6818,77 +6828,27 @@ number, is under *nothing to draw* in §3.4.
6818
6828
  ### 5.1 Compile errors — before the gate
6819
6829
 
6820
6830
  A `CompileError` names the object and the field, and nothing is written. Its line
6821
- ends with ` (see rigc guide §5.1)`: this section, where the tables below find its row
6822
- by its message.
6823
-
6824
- They arrive in two waves, and the wave tells you what kind of mistake it is. The
6825
- first is a **shape** refusal from a spec parser — `parseRigSpec`
6826
- ([`src/rig.ts`](../src/rig.ts)) and `parseMotionSpec`
6827
- ([`src/motion.ts`](../src/motion.ts)) — which run at load, before anything is
6828
- compiled, and ask only what the one file in front of them can answer. Every
6829
- `parseMotionSpec` refusal reads `<file>: \`<key path>\` is <what it actually is>;
6830
- <the spelling that works>`, so its whole wave is **one row per FIELD** rather than
6831
- one per message. (The rig spec parser's messages are prose, so they sit in the
6832
- second table with everything else.)
6833
-
6834
- 🚨 **A key neither format has is refused by name, in both files.** Not a row in
6835
- the table below, because it is not about one field: every object in a rig spec and
6836
- in a motion spec is checked against the keys its shape actually owns, and a key
6837
- outside that set stops the build, because nothing else reads such a key: left
6838
- alone it would be dropped from the emitted skeleton with every assertion green.
6839
-
6840
- ```
6841
- rigc compile error: rig.json: constraint "ctl" (physics) has 4 keys this compiler
6842
- does not read: "scaleYMode" (did you mean "scaleY", "scaleX"?), "scale" (did you
6843
- mean "scaleX", "scaleY"?), "wobble", "ROTATE" (did you mean "rotate"?). Nothing
6844
- reads such a key, so it would be dropped from the emitted skeleton in silence —
6845
- fix the spelling or remove it. Known here: bone, damping, dampingGlobal, fps, …
6846
- ```
6847
-
6848
- Read it as a **repair**, not a rule: every stray key on that object is named at
6849
- once, the closest known spellings come with it (the search is case-insensitive, so
6850
- a real key in the wrong case leads the list), and the shape's whole key set is
6851
- printed after. What it will *not* do is guess — a key four edits from anything gets
6852
- no suggestion, only the set.
6853
-
6854
- ⭐ **The scan runs before the required keys are asked for, in both files**, and
6855
- that is what decides which message a *misspelled* required key gets. Misspelling
6856
- one is the commonest way to lose it, so it is refused as the typo it is rather than
6857
- as the thing it lost:
6858
-
6859
- ```
6860
- rigc compile error: rig.json: this rig spec has a key this compiler does not read:
6861
- "slot" (did you mean "slots"?). Nothing reads such a key, so it would be dropped
6862
- from the emitted skeleton in silence — fix the spelling or remove it. Known here:
6863
- bones, constraints, events, images, invariants, name, note, skeleton, skins, slots,
6864
- spec.
6865
- ```
6866
-
6867
- A key that is **genuinely** absent has no near miss to name, so the scan finds
6868
- nothing and the required-key message below it is what arrives — `a rig spec needs a
6869
- "slots" array (it may be empty; its ORDER is the draw order)` here, and
6870
- `` `animations` is absent; … `` in a motion spec. Read the two apart by that:
6871
- **"does not read"** means the key *is* in your file, spelt some other way, and
6872
- **"needs a …"** / **"is absent"** means it is not in the file at all. Where both
6873
- are true at once — a typo beside a key that really is missing — the typo is named
6874
- first, because it is the one you can fix without re-reading the file.
6875
-
6876
- ⚠️ One check stays above the scan in both parsers: the `spec` version tag. The
6877
- version is what decides *which* key set applies, so a file declaring a version this
6878
- compiler does not know is refused as that — `unknown rig spec version "rigc-rig/2",
6879
- expected "rigc-rig/1"` — rather than key by key against a set it never claimed. The
6880
- price is paid by one spelling: a misspelt `spec` key itself reads as `unknown rig
6881
- spec version undefined, expected "rigc-rig/1"`, which is true and one line short of
6882
- naming the typo.
6883
-
6884
- ⚠️ There is **no forward-compatibility escape**, and no `note` field except where
6885
- one is listed: a rig spec's root, a motion spec's root, an animation, and a
6886
- `physics` tuning entry. Prose anywhere else has to go in a document, because a key
6887
- the compiler tolerates is a key it cannot distinguish from one you meant it to
6888
- read. (The **cut manifest** is deliberately outside this: it is the record of the
6889
- pipeline that produced the art as much as an input, it carries fields the compiler
6890
- states outright that it does not read — `roi` — and it may carry `note` and
6891
- `archetype` as well. It has no shape parse at all.)
6831
+ ends with ` (see rigc guide <CODE>)`; run that exact command first. It prints one
6832
+ row below, naming the shipped file, positional section, line and heading. Each
6833
+ source refusal carries a stable `CE_` code separately from its original message.
6834
+ Library callers may still construct an uncoded `CompileError`; only that legacy
6835
+ case points at `§5.1`. `NotImplementedError` keeps its class and the same pointer.
6836
+
6837
+ Use `rigc guide §5.1.<k>` for a whole numbered `####` group; every group is at most
6838
+ 30,000 UTF-8 bytes including the command's heading. `rigc guide §5.1` prints this
6839
+ introduction and the group index, also at most 30,000 printed UTF-8 bytes;
6840
+ `rigc guide §5.1 --all` explicitly asks for every group's body. The guide remains one ledger:
6841
+ the command reads these rows at call time, without a generated copy. Unknown
6842
+ codes are refused with the three nearest real names and exit 1. `<value>` and
6843
+ other angle-bracket placeholders below stand for values supplied by the input;
6844
+ the fixed message text and conditional/helper alternatives are quoted verbatim.
6845
+
6846
+ Shape refusals run when the rig or motion file is read; meaning refusals can need
6847
+ the other file, the declared names, a property's channels or a key's position.
6848
+ Repair the named input and rebuild. An `internal:` row names a compiler defect:
6849
+ retain the minimal inputs and report that code rather than inventing author data.
6850
+
6851
+ #### 5.1.1 Motion parser field reference
6892
6852
 
6893
6853
  | Key | Refused when it is not | Why the shape matters |
6894
6854
  | --- | --- | --- |
@@ -6931,199 +6891,590 @@ states outright that it does not read — `roi` — and it may carry `note` and
6931
6891
  | `…sequence[i].keys[j].index` | a whole number ≥ 0 | stored as `index << 4`, which truncates a fraction (1.5 shows frame 1). Whether it is inside the series' `count` is the compile-time row below |
6932
6892
  | `…sequence[i].keys[j].delay` | a finite number ≥ 0 — and **above 0 wherever the mode advances**, counting a delay carried from the key before | `(time - keyTime) / 0` is Infinity and `Infinity \| 0` is 0, so a `loop` at delay 0 shows its first frame throughout. The message reads `` `…keys[j]` plays "loop" at a delay of 0 … which is "hold" spelt as "loop" `` |
6933
6893
 
6934
- The second wave is everything that needed the **other** file, the property table
6935
- or the key's position in its own track. These are the frequent ones, verbatim:
6894
+ #### 5.1.2 Input files and editor ordering
6936
6895
 
6937
- | Message | What to change |
6938
- | --- | --- |
6939
- | `a rig spec needs a "name" — a motion spec names it to pick this rig` | §3 — name the rig, and make the motion spec's `archetype` equal it |
6940
- | `a rig spec needs a non-empty "bones" array` | §3.2 — a rig with no bones has nothing to hang a slot on; every one has at least a root |
6941
- | `a rig spec needs a "slots" array (it may be empty; its ORDER is the draw order)` | §3.3 — write `[]` for a rig that draws nothing. ⚠️ These three arrive only when the key is really absent: **misspelt**, it is the unknown-key refusal above, naming what you wrote |
6942
- | `bone "X" names parent "Y", which is not declared before it` | move `Y` earlier in `bones` |
6943
- | `<file>: <where> is a string "5"; a number is required` (also `is a boolean true`, `is an array [1]`, `is null`, `is a number 7; a string is required`, `…; an array of numbers is required`, `…; a boolean (true or false) is required`, `…; a string or null is required`) | §3 / §4 — write the value as the JSON type its field holds: a number as a JSON number (`5`, not `"5"`), a flag as `true`/`false`, a name as a string. Every field of the three input files has one type, and a value of another is refused by the field before any reader does arithmetic on it — which it used to: `"x": "5"` built as `5`, `true` as `1` and `[1]` as `1`, and a `null` built too, all green. An array is typed element by element, so the refusal names the index (`weights[3][1].x`, `vertices[0]`). `null` is refused as `null` except where the field states it means something (`skeleton.width`/`height`, `skeleton.audio`, a slot's and a setup entry's `attachment`, a deform key's `vertices`, the manifest's `image`, `states`, `contact_depth` and `cap_containment_ceiling`). `<where>` is the rig spec's wording (`bone "hip" x`, `skin "default" slot "s" attachment "a" rotation`, `constraint "aim" mix`), the dotted path in the cut manifest (`crop.h`, `parts[2].offset[0]`), and the motion spec's own path (`` `animations."walk".ik[0].keys[0].mix` ``). In the rig spec and the manifest it runs right after the key scan and before every other check, so a field check that used to name a type (a mesh name that is not a string, a `lengths` entry spelt as a string) now reads as this row; in the motion spec it runs after that file's own field checks, which keep their sentences. A closed set of names is not a type, and is the next row's |
6944
- | `<file>: <where> is "foo"; one of "name", "raw" — anything else was read as …` (also `bone "b" from.rotation is 5; one of "axis", "anchor"`, the manifest's `parts[1].mesh.kind is "foo"; one of "ring", "ribbon"`, and `skin "s" slot "x" attachment "a" generator.kind is "foo"; one of "ring", "ribbon", "contour", "grid", "segments"`, or `… generator.kind is absent; …`) | §3.2 / §3.4 — write one of the names listed. A field that holds one of a closed set of names is refused, with the set, when it holds anything else — a number too, since a number is not a name. Most such fields have a reader that refuses by name with its own sentence (`blend`, `inherit`, a constraint's `type`, `scaleY`); these four had none, and each built green or crashed: `boneIndexing` read as `"name"`, `from.rotation` as no rotation, the manifest's `mesh.kind` as a ribbon by one reader and a ring by two others, and a generator `kind` threw a `TypeError`. The sentence after the dash says what the value used to be read as, which is the build you had before this refusal. The first three run right after the type row's walk, before every other check; the generator's `kind` is refused earlier, by the key scan, because it chooses which keys the rest of the generator may hold |
6945
- | `<file>: <where> is Infinity; a number in this file is finite at float32 precision, at most ±3.4028234663852886e+38, because the skeleton is written as float32 — …` (also `is -Infinity`, `is 1e+308`, and `is NaN` from a library caller) | §3 — state the number you meant, inside float32's range. One walk over the whole file, run right after the key scan and before any other rig-spec check, so a range rule never prints `NaN`. `<where>` is every number in the rig spec — a bone (`bone "hip" x`), a slot, a skin's attachment down to its arrays (`skin "default" slot "s" attachment "a" weights[3][1].x`), a constraint (`constraint "aim" mixRotate`), an event, `skeleton`, `invariants.meshTriangles` — and the dotted path in the cut manifest (`crop.h`) and in the motion spec (`` `animations.idle.tracks[0].keys[1].v[0]` ``, after the motion spec's own field checks, which keep their sentences). ⚠️ It sees numbers only: `"x": "NaN"` is a string, and the row above refuses it as one |
6946
- | `two bones are called "X"` | bone names are the join key; rename one |
6947
- | `two ik constraints are called "X" — a constraint resolves by name AND type (\`SkeletonData.findConstraint\`), so names are unique PER KIND: an ik and a transform constraint may share one, two of a kind may not` | §3.5 — rename one of the two. The kind in the sentence is the pair's own, so `two transform constraints are called "X"` is the same refusal on another kind; a name shared **across** kinds is not this error |
6948
- | `ik constraint "X" names 3 bones ("a", "b", "c"); the solver applies one or two, so a constraint over 3 moves nothing — name one bone, or two where the second is the first's child` | §3.5 — the constraint's `bones` is what changes: one bone, or a parent and its child. The runtime's ik update has a case for one bone and one for two, so a longer list loads, sits in the update cache and applies nothing — [measured] every bone posed exactly where the same rig with no constraint has it. A longer chain is several constraints, each over one bone or a pair |
6949
- | `ik constraint "X": "B" is not a child of "A" ("C" stands between), so the two-bone solve is not of the chain drawn — name "B"'s own parent as the first bone, or make "B" a child of "A"` (also `("A" is not above it; its parent is "P")`, `("B" has no parent)`) | §3.5 — the constraint's `bones` is what changes, or `B`'s `parent`. The two-bone solve places `B` through `A`'s matrix from `B`'s own local offset, so what stands between them is left out of the triangle it solves — [measured] a bone between them at `B`'s origin left the tip up to 2.60 off the target, and one at `A`'s origin landed only while it held its identity |
6950
- | `physics constraint "X" is declared in both the rig spec and the motion spec's physics table` | §4.6 — the rig spec declares a physics constraint's structure and the motion spec's `physics` table declares one outright; pick the file it belongs in. Per kind, like every other constraint name: an `ik` "X" in the rig spec beside a `physics` "X" here is two constraints and is not this error |
6951
- | `stops[i] needs a "chain" …` / `stop "C" states "links" …; it is the chain's swinging links, root first …` / `stop "C" needs "against" …` / `stop "C" states no "at" …` / `stop "C" states no "inward"` (or `"outward"`, `"lower.inward"`, `"lower.outward"`) / `stop "C" states no "lower" …` | §3.8 — state the field; a stop has no defaults. `at` is `[x, y]` in `against`'s local space, and `lower` is required on a chain of two or more links |
6952
- | `stop "C" states "at" [V]; it is [x, y], two numbers in "A"'s local space` | §3.8 — two numbers |
6953
- | `stop "C" states "lower" and its chain has one link …` | §3.8 — remove `lower`, or list the links below the first |
6954
- | `stop "C": links[k] names bone "X", which this rig does not declare` / `stop "C": "against" names bone "X", which this rig does not declare` | §3.8 — fix the name; both resolve against the rig spec's own `bones` |
6955
- | `stop "C": links[k] "X" is already stopped by stop "D" …` | §3.8 — a link has one drawn link and one clamp; stop it once |
6956
- | `stop "C": links[k] "X" is the skeleton's root …` / `… takes its place from the manifest ("from") …` | §3.8 — a link hangs from a parent, and its drawn link copies its stated `x`, `y` and `rotation`; state them. The same `from` refusal names a bone the stop's angles are read through |
6957
- | `stop "C": "inward" N is greater than "outward" M …` (also `"lower.inward"`) | §3.8 — the range is `[inward, outward]`, counted positive away from the point; `inward` is the lower end |
6958
- | `stop "C": "outward" N puts "L_d"'s bound at B°, past ±180° …` (also `"inward"`, `"lower.…"`) | §3.8 — the clamp reads a local rotation in (−180, 180]; the bound is the drawn link's rest angle moved by the range, so narrow the range |
6959
- | `stop "C" generates bone "X", which this rig already declares …` / `… generates ik constraint "X" …` / `… generates transform constraint "X" …` / `… which stop "D" generates too …` | §3.8 — the names are the expansion's (`<chain>_touch`, `<chain>_stop`, `<chain>_stop_aim`, `<link>_rel`, `<link>_rel_copy`, `<link>_d`, `<link>_clamp`); rename the bone or constraint, or the `chain` |
6960
- | `stop "C": links[k] "X" is written by no constraint of this rig spec …` | §3.8 — declare what swings the link (a physics constraint, usually) in the rig spec's `constraints`; the motion spec's `physics` table is emitted after the clamp |
6961
- | `stop "C": links[k] "X" does not hang below "P_d", the drawn link of links[k-1] …` | §3.8 — parent the link (or its control bone) below the drawn link above it, so the clamp that holds that one carries it |
6962
- | `stop "C": "against" "A" hangs below "B", which the stop moves …` | §3.8 — name the leg; a point on the chain would swing with it |
6963
- | `stop "C": "at" [x, y] on "A" sits on the root of "L" …` / `… lies on "L"'s own line at the setup pose …` | §3.8 — move the point onto the leg's edge beside the hem; on the link's line it has no side to call inward |
6964
- | `stop "C": "P", where the frame hangs, is scaled unevenly, sheared or reflected …` / `stop "C": "B", between links[k] "L" and the drawn link above it, is scaled unevenly, sheared, reflected or inherits other than normally …` | §3.8 — the stop's angles add only through a rotation and an even scale; take the scale off that bone |
6965
- | `stop "C": "L" hangs below "B", which a later stop generates …` | §3.8 — list that stop first |
6966
- | `physics constraint "X" drives "L", a link stop "C" holds, from the physics table …` | §3.8, §4.6 — declare the constraint in the rig spec's `constraints`, where the stop's copy and clamp are placed after it |
6967
- | `skin "S" lists "X" under "transform", but the rig declares it as a "ik" constraint — a skin looks its constraints up by name AND type, so this one is a miss and the loader throws` | §3.4.8 — move the name to the list named after the constraint's own kind. A name the rig declares under **no** kind is the other miss and says so (`skin "S" activates ik constraint "X", which this rig does not declare`). ⚠️ A name listed by **several skins** is not an error: the lists are per-skin sets and a bone or constraint in two of them is active under either |
6968
- | `slot "X" names bone "Y", which this rig does not declare` | add the bone, or fix the slot's `bone` |
6969
- | `no setup pose for slot "X": give the motion spec a \`setup\` entry or the rig slot an \`attachment\`` | R3 — pick one file and declare it there. A slot **nothing** fills is exempt: its setup pose can only be "show nothing" and is not asked for |
6970
- | `the setup pose shows attachment "A" on slot "X", which no skin and no manifest part fills` | §3.3 — the slot is emitted empty and nothing was ever going to fill it, so `A` resolves to nothing. Give the slot an attachment (a skin entry or a manifest part), or state the setup pose as `null` |
6971
- | `the setup pose shows attachment "A" on slot "X", and the slot is emitted empty because the one manifest state that fills it has no art: "s" (no PNG at p)` | §0.2 — a **different** fault with a similar shape: a manifest part does fill this slot and its art was not where the manifest pointed, so every state of it was dropped. **Restore the file or fix the path** — posing `null` compiles, but it ships the rig with that part missing and the gate green. The path printed is the one rigc tried, which is what tells a deleted file from a misspelt `states:` entry; `all N manifest states that fill it have no art` is the same message where the part has more than one. Under `--atlas-in` the same sentence reads `no region "R" in <atlas>` and asks you to add the region to the pack — no file was opened |
6972
- | `a region needs width and height — give them, or give an "image" and rigc will measure the PNG` | add `image`, or both sizes |
6973
- | `a mesh needs width and height — give them, or give an "image" and rigc will measure the PNG` | §3.4 — the same rule for a mesh |
6974
- | `"type" is null, which is not a name. An attachment's type is one of region, mesh, linkedmesh, … or the key is absent and reads as "region"` | §6 — **remove the key**. Absent is the format's own default; present-and-null matches no parser case and the attachment is dropped in silence |
6975
- | `attachment type "X" is not one of the 7 the Spine 4.3 format defines (…)` | §6 — a name the format does not have. Not a deferral, and not something rigc will grow: fix the spelling (`sequence` is a key on a region or a mesh, not a type) |
6976
- | `this attachment is a "point" … rigc does not emit it yet` | §6 — a construct the format has and rigc does not write. The message says what it would carry; SPEC_COVERAGE part 1-6 is the row it reads from |
6977
- | `a linked mesh needs "source" — the PLACEHOLDER of the mesh whose geometry it draws …` | §3.4 — `source` is what MAKES a mesh linked, and the parser falsy-tests it, so an absent or empty one is read as an ordinary mesh and throws on the `uvs` a link has not got |
6978
- | `a linked mesh states "uvs", "triangles", …, and a linked mesh has no geometry of its own` | §3.4 — remove them, or remove `source` and author this as a mesh. The parser returns before `readVertices`, so those keys are read by nothing at all |
6979
- | `"source" is "X", and skin "S" … slot "L" … holds 2: "a", "b"` | §3.4 — `source` is the PLACEHOLDER the source is filed under, not its `name`. A clause after the skin and after the slot says whether each was stated or taken from the parser's default — **the default skin** and **this attachment's own slot**, which is the pair that surprises |
6980
- | `"slot" is "X", which the rig does not declare as a slot` / `"skin" is "X", … the rig declares no such skin` | §3.4 — a link resolves both by name. Left to the round trip these are the runtime's `Source mesh slot not found` and `Skin not found`, which name neither the attachment nor where it looked |
6981
- | `no "skin" is stated, so the parser looks for the source "X" in the default skin — and this rig declares no default skin` | §3.4 — state the `skin` the source is filed under. A link with no `skin` resolves through `SkeletonData.defaultSkin`, which is null in a file with no default skin, and the runtime reads `getAttachment` off it with a `TypeError` naming nothing |
6982
- | `"source" is "X", which is itself a linked mesh, and a chain of them is refused` | §3.4 — point `source` at the mesh. A chain resolves in file order and loads nothing at all in one of the two orders, silently |
6983
- | `"source" is "X", which is a "region" attachment and not a mesh` | §3.4 — a link takes another MESH's geometry; off any other type the runtime reads `undefined` and says nothing |
6984
- | `… is a boundingbox and states a "sequence". A sequence is a numbered series of atlas regions, and only the 3 kinds that draw a region carry one — region, mesh, linkedmesh …` | §3.4.10 — put the series on a region or a mesh, or remove it |
6985
- | `… "sequence" states no "count" …` / `… "sequence".setup is N, and a C-frame series has frames 0 to C-1 …` / `… "sequence".F is V; it is a whole number …` | §3.4.10 — the parser reads an omitted count as 0 frames and clamps a setup past the end; state the count, and a 0-based `setup` inside it |
6986
- | `… states "image" beside "sequence" …` / `… states "generator" beside "sequence" …` | §3.4.10 — the frames are the images; remove `image`. A sequence mesh takes authored geometry |
6987
- | `… sequence frame I of C (number N) is the region "R", and there is no PNG for it at P …` (or `… which the atlas at A does not have …` under `--atlas-in`) | §3.4.10 — add the frame, or state the `count` the series really has. The compiler draws no frame in place of another |
6988
- | `… the N frames of this sequence measure W1, W2 in width … State "width"` | §3.4.10 — frames of different sizes; state the attachment's size |
6989
- | `animation "A" sequence S/X/P: attachment "P" carries no "sequence" block, so there is no series to step …` | §4.13 — give the attachment a `sequence`, or remove the track |
6990
- | `animation "A" sequence S/X/P (t=T): index I is past the end of a C-frame series …` | §4.13 — `index` is 0-based |
6991
- | `animation "A" sequence S/X/P: attachment "P" is a linked mesh that plays its source's timelines …` | §4.13 — key the source (the link steps its own series by it), or set `"timelines": false` on the link |
6992
- | `a linked mesh needs width and height — give them, or give an "image" and rigc will measure the PNG` | §3.4 — the mesh rule, on a link. Its art is its own |
6993
- | `hull N disagrees with the triangles, whose outline has K vertices (0 → …)` | §3.4 — delete `hull`, or state K |
6994
- | `hull vertices must come first; vertex i is on the boundary and vertex j is not. The triangles' outline runs …: list those K vertices first, in that order, then the M interior vertices` | §3.4 — renumber the vertices: the printed walk first, then the interior |
6995
- | `hull vertices must trace the outline in order; the triangles' outline runs …, so vertex a has to follow vertex b in the list, and vertex c does` | §3.4 — renumber along the printed walk |
6996
- | `the triangles do not tile the outline: …` / `the triangles' outline is not one closed loop: …` | §3.4 — a doubled triangle, an unused vertex, a pinch or a hole in `triangles`. When the message goes on `— the triangles are N pieces that share no vertex …`, the mesh is several meshes: `rigc split` writes one per piece (§3.4.11) |
6997
- | `vertex N binds bone "X", which the rig does not declare as a bone` | §3.4 — an authored mesh's `weights` bind by NAME, like everything else in a rig spec. Fix the spelling, or declare the bone. The message names the skin, the slot, the placeholder and the vertex, because an index would name none of them |
6998
- | `vertex N binds bone index I, which is not in the bone list` | §3.4 — a `"boneIndexing": "raw"` run on a mesh, bounding box, clipping polygon or path names a bone by its place in the bone array, and I is no place in it: past the end, negative or not a whole number. Count the rig's `bones` from 0, or give the bindings by name as `weights`, which cannot miss this way. ⚠️ **Refused earlier, not newly** (issue #917): the run is decoded to bone names once, when the attachment is built, and this is where an index that names no bone stops. Before that a mesh compiled and `A20` named the index at the gate, a bounding box, clipping polygon or path with its `lengths` stated compiled and `A33` named it, and only a path whose `lengths` rigc measures refused here, in this sentence. `MV04` plants it on each of the four kinds |
6999
- | `the raw weighted run has a bone count of C at index I` / `the raw weighted run is truncated — vertex N claims C bone(s) and the array ends first` / `the raw weighted run decodes to N vertices but there are M uv pairs` | §3.4 — a mesh's `"boneIndexing": "raw"` run is not `boneCount, (index, x, y, weight) × boneCount` per vertex, one vertex per uv pair. These are the polygon's three sentences (whose last clause there reads `but vertexCount is M`), now asked of a mesh as well. Fix the run, or give the bindings by name as `weights`. ⚠️ **Refused earlier, not newly** (issue #917): the mesh run is decoded to bone names when the mesh is built, and a run that does not decode cannot be. Before that it compiled and `A20` named it at the gate (`has weights for 5 vertices but 4 uv pairs`, `vertex 3 has weight NaN`). `MV04` plants each |
7000
- | `image "X.png" is not on disk at …` | fix the name, or point `--images` at the right directory |
7001
- | `image "X.png": /…/X.png is a WebP image (…), not a PNG: its first 12 byte(s) are …` | the file is there and is not a PNG — the name ends in `.png` and the bytes decide. Re-export it as PNG; the same sentence says **truncated** for a PNG that runs out before its `IEND`, and then the repair is a whole copy, and names the dimension for a PNG whose `IHDR` states a width or height of 0 (§0.2) |
7002
- | `a "contour" generator traces the part's own alpha, and "X.png" is lifted off a packed page at the coordinates the atlas states, which on this file are not where its texels are — so there is no silhouette here to trace, only another part of the page. page "p.png" declares …` | the page's PNG is not the size its atlas declares, and the rest of the message is `A06`'s sentence for it: re-declare the page with the `scale:` header it names, or re-export the page at its declared size (§0.2) |
7003
- | `--atlas-in <pack>.atlas: N of its M page(s) cannot be read as PNG, and nothing was compiled against the pack — page "p.png": …` | the same, for every page of the pack at once, before the compile: re-export each named page as PNG under the name the atlas gives it (§0.2) |
7004
- | `parts/iris_open.png is 96x64 but slot "iris" declares 96x60` | R5 — a manifest `states:` entry whose art is not the window the part declares. Re-export the PNG, or fix the part's `size`; a quad sized against art of another size is the silence `A06` exists for, and the window is what the quad is built from |
7005
- | `plates/00_stage.png is 256x256 but the manifest window for "stage" is 250x256` | R5 — the same check on the part's unconditional `image`, against the window the crop gives it |
7006
- | `region "00_stage" of <pack>.atlas (declared 256x256 by its offsets) is 256x256 but the manifest window for "stage" is 250x256` | R5 — the row above under `--atlas-in`, and the prefix is the whole point: it says which of the two rigc **measured**, because the remedy differs. A bare path is a loose PNG it opened and you re-export; a `region … of <pack>` was read out of the pack, and you repack or aim the part at another region. This is the size row of §0.2's table, with the message it actually prints |
7007
- | `duplicate region name "X"` | two PNGs share a basename; one part, one page, one name |
7008
- | `"b/X.png" and the art already atlased as region "X" are two different files — … Rename one of the PNGs.` | R5 — the region name is the basename, so only one of the two can hold it. Rename a file (not a placeholder: the placeholder is free to repeat) |
7009
- | `the image "X.png" was never added to the atlas, so there is no region "X" …` | nothing in the spec — every image an attachment names is measured and atlased, one per file whichever skin names it, so this says rigc skipped one. Report it on [the tracker](https://github.com/rig-c/core/issues). The `#555` the message itself cites is the change that made one-per-file an invariant, not a place to file against |
7010
- | `motion spec names archetype "A" but the rig spec at … is called "B"` | make `archetype` equal the rig's `name` |
7011
- | `animation "A" declares duration Ns but its last key is at Ms` | R7 — fix whichever of the two you meant |
7012
- | `animation "A" slot "X" attachment: key at Ns is Ms past the declared duration Ds` | §4.5 — the key is past the end of the animation and nothing will sample it. Move the key onto `duration`, or raise `duration` |
7013
- | `animation "A" slot "X" attachment: attachment "N" is not in slot "X" under any skin (searched: default, alt) — the slot has: plain, trim` | §4.4 — the keyed name is in **no** skin, and the two clauses say where the compiler looked and what it would have taken. Fix the spelling, or give some skin a placeholder called `N`. A name only a NAMED skin fills is not this error — it compiles, and the slot shows nothing under the skins that lack it. `the slot has no attachments at all` is the same message where nothing fills the slot |
7014
- | `animation "A" keys unknown bone "X"` | the track's `bone` is not in the rig |
7015
- | `animation "A" keys physics "*" P, the timeline that names no constraint and drives every physics constraint declaring "PGlobal": true, and none of "C", … does — it would parse and move nothing` | §4.4 — set `"PGlobal": true` on the constraints the track is for (§3.5), or key one by name. For `reset` it reads *every physics constraint the rig has*, and fires only on a rig with none |
7016
- | `` `animations."A".tracks[i].physics` is the string ""; the empty name is how a skeleton file spells a physics timeline that names no constraint, and a motion spec spells that "*" … `` | §4.4 — name one constraint, or write `"*"` |
7017
- | `physics constraint "*": the name is reserved — …` / `` `physics."*"` names a physics constraint "*", and that name is reserved … `` | §3.5 — `"*"` is the target of the timeline that names no constraint; rename the constraint |
7018
- | `animation "A": group "G" lists "*", which is not a constraint but the target that names none …` | §4.4 — write `"*"` as the track's `physics` field |
7019
- | `animation "A" bone "X" translatex: key value must be an array of 1 number(s)` | the value shape must match the property (§4.4) |
7020
- | `animation "A" physics constraint "C" mass key at t=… is 0 (massInverse Infinity); must be > 0 — …` | §4.4 — a keyed physics value outside its row's bound. The message names the bound and then its basis: where the runtime's arithmetic fails, the expression and its lines (`mass` at 0 is the one here, and `damping` below 0); where the value runs and runs wrongly, that refusing it is rigc's call and what the value does. The bounds: `mass` is `> 0`, `damping` is inside `[0, 1)` — `0` included, `1` not, since issue #1422 —, `mix` and `strength` are `0` or more, and `inertia`/`wind`/`gravity` are bounded nowhere. ⚠️ Those are the bounds a **key** is held to. A setup `strength` of `0` is refused too, but by `A23` rather than here, and with its own sentence — `physics "C" has strength 0; nothing pulls it back`; a setup `strength` below 0 says the offset is pushed away and grows, the same arm this message quotes for a negative key. A `damping` key's sentence names the exponent `60 * step` and why a negative is NaN at any `fps` where `60 / fps` is not whole (§4.4) |
7021
- | `a key carries both a named easing and a raw curve; pick one` | R6 |
7022
- | `last key carries an easing but has nothing to ease to` | drop `ease`/`curve` from the final key |
7023
- | `key times must strictly increase (at t=…)` | including after `lag` and `stagger` |
7024
- | `animation "A" has two tracks on X.property; merge them into one track` | one timeline per target property |
7025
- | `group "G" names member "M" twice (at index i and j)` | §4.5.1 — member order is what `stagger` counts and what a value map is read against, so a repeat is two delays and two values for one bone |
7026
- | `group "G" declares no members` | §4.5.1 — a track naming it would compile no timeline and gate green |
7027
- | `animation "A" group "G" P (t=…): the value map names "M", which group "G" does not declare` | §4.5.1 — fix the name, or add the member to the group |
7028
- | `animation "A" group "G" P (t=…): the value map states no value for member "M"` | §4.5.1 — a member is refused rather than defaulted; state every one |
7029
- | `animation "A" group "G" P (t=…): derive <kind> states no depth for member "M"` | §4.5.1 — same rule for the depth table: a member silently at depth 0 would be keyed with a different model from the ones beside it |
7030
- | `animation "A" group "G" P (t=…): this key carries both a "derive" model and a per-member "v" map` | §4.5.1 — two answers to one question; drop one |
7031
- | `animation "A" bone "B" P: a per-member "v" map names members, and a bone track has one target` | §4.5.1 — write the value directly, or move the track onto a group |
7032
- | `animation "A" group "G" P (t=…): derive <kind> has no projection onto "P"` | §4.5.1 — the kind drives one displacement axis and one scale axis; state the axis, or write a `v` map |
7033
- | `animation "A" group "G" P (t=…): derive … These members sit under N different parents` | §4.5.1 — coordinates measured from different origins; split the track by parent |
7034
- | `animation "A" group "G" P (t=…): derive <kind> projects onto "scaleX" and member "M" states depth −z` | §4.5.1 — a foreshortening needs the part in front of the axis; a part behind it takes the displacement projection |
7035
- | `animation "A" group "G" P (t=…): derive <kind> states carried=… on a "scalex" track` | §4.5.1 — the foreshortening reads no depth difference, so `carried` belongs on the displacement track |
7036
- | `animation "A" group "G" P (t=…): derive <kind> turns member "M" … past its own edge` | §4.5.1 — `cos(α − t) ≤ 0` would mirror the drawing; the turn is past what this construction carries (FACE §8) |
7037
- | `no stage size: give the rig spec a \`skeleton.width\`/\`skeleton.height\`` | §3.1 — or state `"width": null, "height": null` if the skeleton you are transcribing declares no stage |
7038
- | `"skeleton" states width: null and a height of N` / `states height: null and a width of N` | §3.1 — a stage has both extents or neither |
7039
- | `"skeleton" declares no stage (width: null, height: null) and still states x` | §3.1 — an origin for a box that is not there |
7040
- | `N mesh slot(s) emitted but the rig "X" allows 0 — a mesh rigc GENERATED counts against \`invariants.meshSlots\`…` | §3.4 / §3.7 — a rig that invokes a mesh generator declares the budget; undeclared is zero. Add `"invariants": { "meshSlots": N, "meshTriangles": M }` |
7041
- | `drawOrder at t=…: slot "X" is not one this rig emits` / `is offset twice in one key` / `puts it at N, outside the … emitted slots` | §4.7 |
7042
- | `events at t=…: event "X" is not declared in the rig spec's "events" block` | declare it in the rig spec (§3.6), or fix the name |
7043
- | `events: key times must not go backwards` | put the firings in time order (§4.8) |
7044
- | `events at t=…: volume is set but event "X" declares no "audio"` | drop `volume`/`balance`, or give the event an audio path |
7045
- | `vertexCount is undefined; a polygon needs at least 3 vertices, stated outright` | give the bounding box or clipping attachment a `vertexCount` (§3.4) |
7046
- | `vertexCount N wants M unweighted numbers and "vertices" holds K` | fix the count or the array; they decide the encoding between them |
7047
- | `end names slot "X", which this rig does not declare` | fix the clipping attachment's `end`, or add the slot |
7048
- | `bone "X" takes its position from …, which needs a cut manifest` | R8 — pass `--manifest`, or write literal `x`/`y` |
7049
- | `animation "A" keys unknown ik constraint "X"; the rig declares ik constraint(s): …` | §4.9 — fix the name, or declare the constraint in the rig spec |
7050
- | `animation "A" keys "X" as an ik constraint, but the rig declares it as a "transform" constraint` | §4.9 — a timeline's target resolves by name AND type; put the entry under the right group |
7051
- | `ik constraint "X": key 0 names "softness" and key 1 (t=…) does not` | §4.9 — every key is read with its own default, so state the field on every key or on none |
7052
- | `ik constraint "X" (t=…): mix is 1.5, outside 0..1` | §4.9 — an IK mix is a percentage; a transform mix is unbounded |
7053
- | `deform …: the run starts at deform index 4 and is 6 long, which ends at 10; this attachment's deform array is 8 long (4 vertices)` | §4.11 — shorten the run or move its start; the parser would drop the tail in silence. The count in brackets is the **target's own**: a mesh's or a path's vertices, or a weighted attachment's bone influences |
7054
- | `deform …: "fromVertex" counts VERTICES, and this attachment is weighted … vertex 2 has 2 of them` | §4.11 — key the control bone, or write bind-space pairs and start with `offset` |
7055
- | `deform …: slot "X" in skin "default" has no attachment "Y" (it has: …)` | §4.11 — fix the placeholder name |
7056
- | `deform … (t=…): the key carries both a "transform" and a "vertices" run` | §4.11.1 — a model and a table are two answers to one question; drop one |
7057
- | `deform … (t=…): the key states a "transform" and a start index` | §4.11.1 — a model covers every vertex, so drop the index or write the partial run by hand |
7058
- | `deform … (t=…): … has a vertex the arithmetic cannot place — vertex v's N weights sum to …` | §4.11.1 — a model lands a vertex by `D · Σ wᵢ`, so the weights have to close at 1; fix them, or write the pairs with `offset` |
7059
- | `deform … (t=…): transform yaw has radius R, and vertex v sits at x=… past it` | §4.11.1 — the cylinder has no surface there; raise the radius to where the part sits |
7060
- | `deform … (t=…): transform affine has scale […], whose determinant is …` | §4.11.1 — at or below zero the map reverses every triangle |
7061
- | `deform … (t=…): transform <kind> states …, and every one of this attachment's N vertices evaluates to an offset of 0` | §4.11.1 — the parameters state a deformation and the geometry sampled it to nothing; the message names the measured cause. A key that means the setup pose states the identity in its parameters, or carries no run |
7062
- | `deform … (t=…): transform field "envelope.<field>" is …` | §4.11.1 `envelope` — the field the message names: `from` and `to` differ, `axis` is a unit direction, `shape` is `"linear"` or `"smooth"`, a `mask` is this attachment's own soft mask, and a weight is in [0, 1] |
7063
- | `deform … (t=…): transform <kind> states … and envelope … weighs every one of them 0` / `… it changes no emitted number` | §4.11.1 `envelope` — the ramp does not cross the part; the message says where its vertices sit along the axis |
7064
- | `vertexCount is N, which is not a multiple of 3` | §3.4 — a path's vertices are knots and handles read in groups of three: `3(K + 1)` open, `3K` closed |
7065
- | `vertexCount is N and an open path needs at least 6` | §3.4 — an open path drops its first and last point, so it needs six for one curve |
7066
- | `"lengths" has N entry(ies) where the parser sizes M — vertexCount / 3 on …` | §3.4 — `vertexCount / 3` entries on either shape; give the array the source states, or leave the field out and rigc measures it |
7067
- | `"lengths"[i] is V, below …` / `"lengths"[i] is "…"; every entry is a finite cumulative length` | §3.4 — the array is cumulative, so each entry is at least the one before it |
7068
- | `rig constraint "X": slot "Y" has no path attachment in any skin` | §3.5.1 — give that slot a `"type": "path"` attachment, or aim the constraint at the slot that has one |
7069
- | `rig constraint "X": rotateMode is "CHAINSCALE"; known: Tangent, Chain, ChainScale` | §3.5.1 — only the first letter's case is free; anything else resolves to `undefined` in the parser |
7070
- | `<file>: slot "X" has blend "ADDITIVE"; known: normal, additive, multiply, screen (only the first letter's case is free — …)` | §3.3 — write the mode in lower case, or with only its first letter upper-cased. `SkeletonJson` reads `blend` through `Utils.enumValue`, which upper-cases the first character and looks the rest up exactly, so `ADDITIVE` loaded as no mode at all (`tools/pose_oracle.ts dump` reads it as `null`), with no error. rigc used to compare the name case-insensitively and build that file green |
7071
- | `rig constraint "X": applies animation "Y", which the motion spec does not declare (it declares: …)` | §3.5.2 — fix the slider's `animation`, or add it to the motion spec |
7072
- | `rig constraint "X": applies animation "Y", which the Spine file lists at index I of its animations and the Spine editor sorts to index J — so an editor import repoints this slider to "Z" …` | **R10** — a JSON object lists every array-index name (`5`, `10`) first, the editor re-sorts the animations and keeps a slider's by index (measured, R10's dated record). Rename the array-index animation names the message lists — a prefix or a leading zero (`a5`, `05`) is enough |
7073
- | `rig constraint "X": declares both a "bone" and "time"` | §3.5.2 — `bone` picks the model and `time` belongs to the other one |
7074
- | `rig constraint "X": declares "property" but no "bone"` | §3.5.2 — name the driving bone, or key `slider.<name>.time` instead |
7075
- | `rig constraint "X": drives off bone "Y" rotate with "local": false, and the driving values that reach animation "A" (0s..Ds) run from −15.000° to 15.000° … the whole part of the range below 0° is dead` | §3.5.2 — add `"local": true`, which reads the bone's own rotation signed and unwrapped, or move the range so it does not cross 0°. A world rotation is wrapped into `[0, 360]` before the slider maps it, so the negative half of the range is unreachable and pins to one frame |
7076
- | `… run from 300.000° to 500.000° … the whole part of the range past 360° is dead` | §3.5.2 — the same wall at the other end, and the same first repair: `"local": true`, or move the range so it does not run past 360°. `[0, 360]` is the whole of what that reader returns, so a bone turned to 500° is read as 140° and selects a time far from the one the range asked for. Ending *exactly* on 360° is fine — that is the full turn, and it misses nothing: the wrap rounds, so a bone a hair below 0° is read as exactly 360 |
7077
- | `rig constraint "X": drives off bone "Y" scaleX with "local": false, … run from -2.000 to 2.000 … Positions below 0 read as the mirror of positions above it: 2.000 of the range below 0 repeats 0.000..2.000` | §3.5.2 — a world scale reading is `Math.sqrt(a² + c²)`, a magnitude, so the half of the range below 0 is the half above it played backwards. Add `"local": true`, which reads `source.scaleX` signed, or move the range so it does not dip below 0. A bottom of exactly 0 is fine — that floor is reached, not approached |
7078
- | `… run from -6.000 to -2.000 … the whole 4.000 of this range is below 0, so it reaches none of the animation's 1s` | §3.5.2 — the same floor with the range wholly under it: every value the reader can return maps past the animation, so the dial holds one frame at every position. The figure is the width below 0, not the reach to the far end |
7079
- | `skin "S" activates bone "B", but that bone does not declare \`"skin": true\`` | §3.4.8 — the list and the flag are one switch; add the flag or drop the list |
7080
- | `bone "B" declares \`"skin": true\` but no skin activates it` | §3.4.8 — the other half: list it in the skin it belongs to, or drop the flag |
7081
- | `skin "S": uses the long form … and also has a key "X"` | §3.4.8 — move the slot inside `attachments` |
7082
- | `animation "A" keys "X" as a path constraint, but the rig declares it as a "slider"` | §4.12 — a timeline group resolves by name AND type; use the field named after the constraint's own type |
7083
- | `animation "A": "position" is a path constraint timeline, and this track names no constraint` | §4.12 — put the name in `"path"` |
7084
- | `rgba value needs 4 channels, got 3` | §4.4 — an `rgba` key is `[r, g, b, a]`. It names no animation, slot or key time, and the only input that reaches it is a slot `rgba` key: the setup pose's `color` is refused earlier, by its own row, with the slot named |
7085
- | `rgba2 value needs 7 channels, got 6` | §4.4 — an `rgba2` key is `[lr, lg, lb, la, dr, dg, db]`: the light colour with its alpha, then the dark colour **without** one. Six is the commonest way to get it wrong, because the dark half looks like it should take an alpha too — the format has no channel for it, and neither does the runtime's `setFrame`. Like the row above it names no animation or key time; the only input that reaches it is a slot `rgba2` key |
7086
- | `rgb value needs 3 channels, got 4` · `alpha value needs 1 channel, got 2` · `rgb2 value needs 6 channels, got 7` | §4.4 — the separable shapes, refused in the words the two above use: an `rgb` key is `[r, g, b]`, an `alpha` key is `[a]`, an `rgb2` key is `[lr, lg, lb, dr, dg, db]`. Four channels on an `rgb` track is the likeliest way to get it wrong — the `rgba` spelling on the timeline that exists to leave the alpha alone — and seven on `rgb2` is the `rgba2` spelling |
7087
- | `animation "A" slot "X" alpha: alpha key value must be [a]` | §4.4 — an alpha key's `v` is a one-element array like every other one-channel track, even though the file writes it bare (`{ time, value }`). The same row exists for each colour shape with its own spelling (`rgb key value must be [r,g,b]`, …) |
7088
- | `animation "A" slot "X" alpha: key at t=T is V; an alpha is a number from 0 to 1 …` | §4.4 — the one colour key stored as a number, so the one nothing clamps on the way out. The runtime clamps the posed alpha only after interpolating, so a key outside 0..1 bends the curve toward a value no pose holds; state the value you mean. 0 and 1 themselves are taken |
7089
- | `animation "A" slot "X": tracks "P" and "Q" both key the slot's alpha — a colour timeline poses its channels at every time …` | §4.4 — two colour tracks of one slot that pose a shared channel (`rgba` + `alpha`, `rgba` + `rgb`, `rgba2` + `rgb2`, …). Each poses its channels at every time, its setup value before its first key included, so the later in the file overwrites the other everywhere and one of them is read by nothing. Key each channel once: `rgb` and `alpha` for two halves on their own key times, `rgba` for both together. The channel named is whichever the two share — `light rgb`, `alpha`, `dark colour` |
7090
- | `animation "A" bone "B" has no timeline "P" (it has: translate, translatex, translatey, scale, scalex, scaley, shear, shearx, sheary, rotate, inherit)` | §4.4 — a bone has exactly eleven timelines and `P` is none of them. Fix the spelling — the single-axis ones are lower-case (`translatex`, not `translateX`). A **constraint** property is refused first, by its own row, naming the field its constraint's name goes in. When `P` is a slot timeline the message says so and where to put the name: `. "rgba" is a slot timeline — put the name in "slot"` |
7091
- | `animation "A" bone "B" inherit key at t=T carries an easing ("E"), and this timeline is stepped by the format — its reader builds no curve, so the mode changes AT the key and holds until the next one. Remove it` (and `… carries a curve, …` for a raw `curve`) | §4.4 — an `inherit` key is a mode, not a value between two others: the parser's `inherit` branch reads `time` and `inherit` and nothing else, so an easing would be written into a key nobody reads (`A05_CURVE_ARRAY_LENGTH` refuses the same `curve` on a file rigc did not write). `"stepped"` is refused too, for the same reason — the timeline already is. Delete the `ease` or `curve` |
7092
- | `animation "A" bone "B" inherit key at t=T names mode "M"; known: normal, onlyTranslation, noRotationOrReflection, noScale, noScaleOrReflection — the runtime folds the case of the first letter and of nothing else` | §4.4 — `M` is not one of the five. The list and the rule are the setup field's (§3.2) — one resolver reads both — so `NoScale` compiles (and is written `noScale`, the editor's spelling) while `NOSCALE` and `noscale` do not: the runtime would load either as **no mode**, and the bone would keep whatever world transform it had |
7093
- | `bone "B" has inherit "M"; known: normal, onlyTranslation, noRotationOrReflection, noScale, noScaleOrReflection — the runtime folds the case of the first letter and of nothing else` | §3.2 — the setup half of the row above, and the same list. The check is exactly as wide as the runtime: `"NOSCALE"` would load as no mode, so the bone's world rotation, scale and shear would never be computed — every attachment on it collapses to a point. Fix the spelling |
7094
- | `animation "A" group "G" has no timeline "P" (a bone group has: translate, translatex, translatey, scale, scalex, scaley, shear, shearx, sheary, rotate, inherit; a slot group has: attachment, rgba, rgb, alpha, rgba2, rgb2; a physics constraint group has: inertia, strength, damping, mass, wind, gravity, mix, reset)` | §4.3, §4.4 — a group's family is decided by the property, and `P` is in none of the three tables, so there is no family to resolve the members as. Fix the spelling and the group becomes whichever family the property names. The group is refused before its members are looked up, so a member the rig does not declare is a **later** message; an unknown group NAME is an earlier one |
7095
- | `animation "A" slot "X" has no timeline "P" (it has: attachment, rgba, rgb, alpha, rgba2, rgb2)` | §4.4 — a slot has exactly six timelines — every one the format has — and `P` is none of them. Fix the spelling; a bone or constraint property written on a slot track is refused by its own row instead |
7096
- | `animation "A" slot "X" rgba2: slot "X" declares no setup "dark", and an "rgba2" timeline poses a slot's dark colour …` — and the same with `rgb2` | §3.3, §4.4 — the two-colour tint has a setup half and a keyed half, and the keyed half cannot exist without the other. `Slot`'s constructor allocates a dark colour only for a slot whose setup pose declares one, and `RGBA2Timeline` writes it unconditionally — so without the `dark` the file loads, and the first `state.apply` throws `TypeError: null is not an object` in the consumer's process. Give the slot the `dark` it holds at rest, or key `rgba` (for `rgb2`, `rgb`) if only the light colour moves. `RGB2Timeline` is measured to throw the same way. Raised before the keys are read, with the slot named, for the same reason the row above is |
7097
- | `N pair(s) of animation names have no one order: … "Fx/a" / "fx/b" (folder) — "Fx/a" and "fx/b" sit in the sibling folders "Fx" and "fx", which the comparator leaves in one place …; rename one of the two folders so they differ by more than letter case, spacing or a leading zero` | **R10** — rename until no pair is left. The kind in brackets says which of the three things the five stored round trips leave open decides the pair: `number` (two digit runs that are each one number written twice, pointing opposite ways), `separator` (a whitespace character that is not a space) or `folder` (two sibling folders the comparator cannot separate). rigc keys `animations` in the editor's own comparator, read off `fixtures/editor-order/probe{1..5}.{in,out}.json` — so a pair those files settle is emitted rather than refused, **including a pair that differs only in case**, whose order is then the one your spec declared. On the three that are left, the editor's re-key repoints every slider whose animation moves index |
7098
- | `N pair(s) of skin names have no one order: … "Fx/a" / "fx/b" (folder) — …` | **R11** — rename until no pair is left. The same shape and the same three kinds as the row above, because it is the same comparator: two of the five round trips carried one name list as both collections and both came back in one order |
7099
- | `slot "patch": placeholder "patch" is filled by the "default" skin AND by skins "zulu", "mike", and the Spine editor has no way to hold that … Move the default skin's entry for this slot into a named skin — call it "base"` | **R12** — do what it says: move that entry out of `default` into a named skin. The editor has no representation for a placeholder the default skin shares with a named one, in either spelling, and §3.4.9 has both measurements. Renaming the placeholder does not help; the shape is what is refused |
7100
- | `skin "S" slot "X" attachment "P": "name" is V, which is not a string. An attachment's name is the runtime's `Attachment.name` …` | §3.4 — write the name as a string, or leave the key out and the attachment is named by its placeholder. It is written verbatim and `path` defaults to it, so a number there would reach the atlas as a region name nobody spelled |
7101
-
7102
- ⚠️ **One refusal in this section is not a `CompileError`, and it is `explain`'s.**
7103
- `explain` prints the `DEFORM` block by **posing** the rig, and spine-core's pose
7104
- resolves every attachment against the atlas — so it needs the art `build` needs,
7105
- reached the same two ways (§0.2). (Since issue #1019 a build's survey is read and
7106
- posed through rigc's own core by default, which reads no atlas; the refusal below
7107
- is unchanged and comes before either.) A pair whose art it cannot resolve is refused **before a line of
7108
- the report**, at **exit 2**, in rigc's own sentence:
7109
-
7110
- ```
7111
- rigc explain: skin "default" slot "lamp" placeholder "shade": attachment "shade"
7112
- wants region "shade", which this build's atlas does not have (it declares no region
7113
- at all). `explain` poses the rig to measure its deform keys and a pose resolves
7114
- every attachment against the atlas, so there is nothing to pose it against. Art
7115
- reaches a compile two ways and this run took neither: `--atlas-in <pack.atlas>`
7116
- resolves the parts against a pack somebody already made, and an "image" per
7117
- attachment resolves them as loose PNGs under `--images <dir>` — a spec that states
7118
- a size and names no image is what `ingest --art none` writes, and `--atlas-in` is
7119
- what reads it. 1 of 1 attachment lookup(s) here resolve to no region.
7120
- ```
7121
-
7122
- Both halves of it are measured rather than fixed text: the count is this pair's, and
7123
- where the atlas has a **near miss** the sentence prints that too, in `A08`'s own
7124
- clause and `A08`'s own words. When `--atlas-in` **was** given and the region is still
7125
- absent, the second half names the pack instead and asks you to fix the spec's region
7126
- name or point the flag at the pack that has it.
6896
+ | Code | Fixed message text and alternatives | What to change |
6897
+ | --- | --- | --- |
6898
+ | <a id="CE_COMPILE_EDITOR_NAME_ORDER_AMBIGUOUS"></a>`CE_COMPILE_EDITOR_NAME_ORDER_AMBIGUOUS` | “"&lt;value&gt;" and "&lt;value&gt;" hold more than one digit run that is the same number written two ways, and those runs point opposite ways — the round trips measured the editor deferring one such run and never two”<br>“"&lt;value&gt;" and "&lt;value&gt;" sit in the sibling folders "&lt;value&gt;" and "&lt;value&gt;", which the comparator leaves in one place — and a tie is kept in file order, which orders two entries but does not say the editor keeps either folder's entries together”<br>“&lt;value&gt; pair(s) of &lt;value&gt; have no one order: &lt;value&gt;&lt;value&gt;[. …and &lt;value&gt; more pair(s) / ]”<br>“animation names”<br>“rename one of the two folders so they differ by more than letter case, spacing or a leading zero”<br>“rename so the only whitespace in either name is a space”<br>“rigc keys the emitted "animations" object in the Spine editor's own comparator, read off five round trips through a licensed 4.3.26 editor (#728) — case folded upward, digit runs read as numbers, spaces skipped, leaves before folders at the root and folders before leaves inside one, and a remaining tie left in the order this spec declares. Each pair below is one those round trips leave open. A slider's animation is an ORDINAL in the format's binary half, and an editor that keys these differently repoints every slider whose animation moves index — silently, in a file that still parses (#535). ”<br>“rigc writes the emitted "skins" array with "default" first and the rest in the same comparator the "animations" object is keyed in — one comparator, measured on round trips that carried one name list as both collections (#728) — and each pair below is one those round trips leave open. A skin is an ORDINAL in the format's binary half — `skins[readInt()]` for an attachment timeline, `skins[skinIndex]` for a linked mesh — so an editor that writes them in another order repoints every such reference, silently, in a file that still parses. ”<br>“skin names”<br>“the order of "&lt;value&gt;" and "&lt;value&gt;" turns on a whitespace character that is not a space, and the round trips measured the editor skipping the space alone”<br>“write each number one way — rename so no digit run in either name has a second spelling”<br>Also: “"&lt;value&gt;" / "&lt;value&gt;" (&lt;value&gt;) — &lt;value&gt;; &lt;value&gt;” | Rename the conflicting animations or skins as the message directs so the file and editor have one order. |
6899
+ | <a id="CE_COMPILE_FLOAT32_DECIMAL_UNREPRESENTABLE"></a>`CE_COMPILE_FLOAT32_DECIMAL_UNREPRESENTABLE` | “no decimal of at most 9 significant digits names the float32 of &lt;value&gt;” | Report the input number and this compiler defect; float32 emission must find a decimal without changing the value. |
6900
+ | <a id="CE_COMPILE_KEY_AFTER_DURATION"></a>`CE_COMPILE_KEY_AFTER_DURATION` | “&lt;value&gt;: key at &lt;value&gt; is &lt;value&gt;s past the declared duration &lt;value&gt;s — nothing that plays this animation for the duration it declares ever reaches it. Move the key to &lt;value&gt;, or declare the duration you meant.”<br>Also: “{&lt;value&gt;s / t=&lt;value&gt;, &lt;value&gt;s after lag/stagger}” | Move the key within the declared duration, or state the duration the animation actually has. |
6901
+ | <a id="CE_COMPILE_RGBA_CHANNEL_COUNT"></a>`CE_COMPILE_RGBA_CHANNEL_COUNT` | “rgba value needs 4 channels, got &lt;value&gt;” | Supply four rgba channels. |
6902
+ | <a id="CE_COMPILE_RGBA2_CHANNEL_COUNT"></a>`CE_COMPILE_RGBA2_CHANNEL_COUNT` | “rgba2 value needs 7 channels, got &lt;value&gt;” | Supply seven rgba2 channels. |
6903
+ | <a id="CE_COMPILE_COLOUR_CHANNEL_COUNT"></a>`CE_COMPILE_COLOUR_CHANNEL_COUNT` | “&lt;value&gt; value needs &lt;value&gt; channel[ / s], got &lt;value&gt;” | Supply the channel count named for this colour shape. |
6904
+ | <a id="CE_COMPILE_JSON_READ_FAILED"></a>`CE_COMPILE_JSON_READ_FAILED` | “cannot read &lt;value&gt;: &lt;value&gt;”<br>Also: “&lt;value&gt; (line &lt;value&gt;, column &lt;value&gt;)” | Fix the named JSON file's path, permissions or JSON syntax. |
6905
+ | <a id="CE_COMPILE_IMAGE_MISSING"></a>`CE_COMPILE_IMAGE_MISSING` | “image "&lt;value&gt;" is not on disk at &lt;value&gt;”<br>Also: “&lt;value&gt;.png” | Supply the PNG at the named images path or correct the image name. |
6906
+ | <a id="CE_COMPILE_IMAGE_PNG_INVALID"></a>`CE_COMPILE_IMAGE_PNG_INVALID` | “&lt;value&gt; is &lt;value&gt;, not a PNG: its first &lt;value&gt; byte(s) are &lt;value&gt;, where a PNG's first 8 are &lt;value&gt;&lt;value&gt;. rigc reads PNG and nothing else — its page-size and alpha readers, its renderer and its region lift all decode PNG, and it links no decoder for any other format — so nothing in this file was measured. Re-export it as PNG”<br>“&lt;value&gt; is a PNG whose IHDR chunk declares &lt;value&gt; byte(s) of data, where the format's is 13”<br>“&lt;value&gt; is a PNG whose IHDR chunk states its size as &lt;value&gt;x&lt;value&gt;: &lt;value&gt; 0, where the format requires each dimension to be at least 1, so the file describes no texel and nothing in it can be measured or drawn. Re-export it”<br>“&lt;value&gt; is a PNG whose first chunk is &lt;value&gt; rather than the IHDR the format requires first”<br>“&lt;value&gt; is a truncated PNG: it is &lt;value&gt; byte(s) long and &lt;value&gt;, so no reader can decode it. Re-export or re-copy the file whole”<br>“&lt;value&gt; is a truncated PNG: it is &lt;value&gt; byte(s) long and ends &lt;value&gt; byte(s) into the 8-byte PNG signature, so no reader can decode it. Re-export or re-copy the file whole”<br>“&lt;value&gt; is a truncated PNG: it is &lt;value&gt; byte(s) long and ends after the signature with no IEND chunk, so no reader can decode it. Re-export or re-copy the file whole”<br>“&lt;value&gt; is a truncated PNG: it is &lt;value&gt; byte(s) long and its &lt;value&gt; chunk at byte &lt;value&gt; declares &lt;value&gt; byte(s) of data, which with its CRC runs to byte &lt;value&gt;, so no reader can decode it. Re-export or re-copy the file whole”<br>“&lt;value&gt; is a truncated PNG: it is &lt;value&gt; byte(s) long and {ends after &lt;value&gt; with no IEND chunk / ends &lt;value&gt; byte(s) into the header of the chunk after &lt;value&gt;}, so no reader can decode it. Re-export or re-copy the file whole”<br>“&lt;value&gt; is empty (0 bytes), and a PNG's first 8 bytes are &lt;value&gt;”<br>“[; its name ends in .png, and it is the bytes that decide what a file is / ]”<br>“[its width and its height are / [its width is / its height is]]”<br>“a &lt;value&gt; image”<br>“a WebP image (a RIFF/WEBP container whose first chunk is &lt;value&gt;)”<br>“image "&lt;value&gt;": &lt;value&gt;”<br>“in no image format rigc recognises by its signature (it names &lt;value&gt; when it meets them)”<br>Here the values named in the message include: “KTX2”, “GIF”, “JPEG”. | Supply a readable PNG with the required header and dimensions at the named path. |
6907
+ | <a id="CE_COMPILE_ATLAS_INPUT_MISSING"></a>`CE_COMPILE_ATLAS_INPUT_MISSING` | “--atlas-in names &lt;value&gt;, which is not on disk” | Correct --atlas-in or supply the atlas file at that path. |
6908
+ | <a id="CE_COMPILE_ATLAS_INPUT_EMPTY"></a>`CE_COMPILE_ATLAS_INPUT_EMPTY` | “--atlas-in &lt;value&gt; declares no regions” | Use an atlas declaring the regions the rig needs. |
6909
+ | <a id="CE_COMPILE_ATLAS_PAGES_UNREADABLE"></a>`CE_COMPILE_ATLAS_PAGES_UNREADABLE` | “--atlas-in &lt;value&gt;: &lt;value&gt; of its &lt;value&gt; page(s) cannot be read as PNG, and nothing was compiled against the pack — &lt;value&gt;”<br>“&lt;value&gt; is &lt;value&gt;, not a PNG: its first &lt;value&gt; byte(s) are &lt;value&gt;, where a PNG's first 8 are &lt;value&gt;&lt;value&gt;. rigc reads PNG and nothing else — its page-size and alpha readers, its renderer and its region lift all decode PNG, and it links no decoder for any other format — so nothing in this file was measured. Re-export it as PNG”<br>“&lt;value&gt; is a PNG whose IHDR chunk declares &lt;value&gt; byte(s) of data, where the format's is 13”<br>“&lt;value&gt; is a PNG whose IHDR chunk states its size as &lt;value&gt;x&lt;value&gt;: &lt;value&gt; 0, where the format requires each dimension to be at least 1, so the file describes no texel and nothing in it can be measured or drawn. Re-export it”<br>“&lt;value&gt; is a PNG whose first chunk is &lt;value&gt; rather than the IHDR the format requires first”<br>“&lt;value&gt; is a truncated PNG: it is &lt;value&gt; byte(s) long and &lt;value&gt;, so no reader can decode it. Re-export or re-copy the file whole”<br>“&lt;value&gt; is a truncated PNG: it is &lt;value&gt; byte(s) long and ends &lt;value&gt; byte(s) into the 8-byte PNG signature, so no reader can decode it. Re-export or re-copy the file whole”<br>“&lt;value&gt; is a truncated PNG: it is &lt;value&gt; byte(s) long and ends after the signature with no IEND chunk, so no reader can decode it. Re-export or re-copy the file whole”<br>“&lt;value&gt; is a truncated PNG: it is &lt;value&gt; byte(s) long and its &lt;value&gt; chunk at byte &lt;value&gt; declares &lt;value&gt; byte(s) of data, which with its CRC runs to byte &lt;value&gt;, so no reader can decode it. Re-export or re-copy the file whole”<br>“&lt;value&gt; is a truncated PNG: it is &lt;value&gt; byte(s) long and {ends after &lt;value&gt; with no IEND chunk / ends &lt;value&gt; byte(s) into the header of the chunk after &lt;value&gt;}, so no reader can decode it. Re-export or re-copy the file whole”<br>“&lt;value&gt; is empty (0 bytes), and a PNG's first 8 bytes are &lt;value&gt;”<br>“[; its name ends in .png, and it is the bytes that decide what a file is / ]”<br>“[its width and its height are / [its width is / its height is]]”<br>“a &lt;value&gt; image”<br>“a WebP image (a RIFF/WEBP container whose first chunk is &lt;value&gt;)”<br>“in no image format rigc recognises by its signature (it names &lt;value&gt; when it meets them)”<br>Also: “page "&lt;value&gt;": &lt;value&gt;”<br>Here the values named in the message include: “KTX2”, “GIF”, “JPEG”. | Supply readable PNG pages at the atlas page paths named in the message. |
6910
+ | <a id="CE_COMPILE_ATLAS_REGION_UNKNOWN"></a>`CE_COMPILE_ATLAS_REGION_UNKNOWN` | “image "&lt;value&gt;" resolves to region "&lt;value&gt;", which the atlas at &lt;value&gt; does not have. [Did you mean &lt;value&gt;? / ]The atlas declares &lt;value&gt; region(s): &lt;value&gt;”<br>Also: “&lt;value&gt;.png” | Correct the image's region name or add that region to the imported atlas. |
6911
+ | <a id="CE_COMPILE_ATLAS_REGION_PAGE_MISSING"></a>`CE_COMPILE_ATLAS_REGION_PAGE_MISSING` | “region "&lt;value&gt;" sits on page "&lt;value&gt;" of &lt;value&gt;, which is not on disk at &lt;value&gt;” | Supply the PNG page named by this region at the atlas-relative path. |
6912
+ | <a id="CE_COMPILE_ATLAS_REGION_OUTSIDE_PAGE"></a>`CE_COMPILE_ATLAS_REGION_OUTSIDE_PAGE` | “region "&lt;value&gt;" is at &lt;value&gt;,&lt;value&gt; sized &lt;value&gt;x&lt;value&gt; on a &lt;value&gt;x&lt;value&gt; page in &lt;value&gt;; the rectangle runs off the page, so its UVs would leave the texture” | Correct the atlas bounds so this region's rectangle stays on its page. |
6913
+
6914
+
6915
+ #### 5.1.3 Manifest, setup and animation targets
6916
+
6917
+ | Code | Fixed message text and alternatives | What to change |
6918
+ | --- | --- | --- |
6919
+ | <a id="CE_COMPILE_MOTION_ARCHETYPE_MISMATCH"></a>`CE_COMPILE_MOTION_ARCHETYPE_MISMATCH` | “motion spec names archetype "&lt;value&gt;" but the rig spec at &lt;value&gt; is called "&lt;value&gt;"” | Make the motion archetype name match the rig's name. |
6920
+ | <a id="CE_COMPILE_STAGE_SIZE_MISSING"></a>`CE_COMPILE_STAGE_SIZE_MISSING` | “no stage size: give the rig spec a `skeleton.width`/`skeleton.height`, or compile against a cut manifest whose `crop` states them, or state `"width": null, "height": null` for a skeleton that declares no stage” | State skeleton.width/height, supply a manifest crop, or declare both dimensions null. |
6921
+ | <a id="CE_COMPILE_REGION_NAME_DUPLICATE"></a>`CE_COMPILE_REGION_NAME_DUPLICATE` | “duplicate region name "&lt;value&gt;" (&lt;value&gt;)”<br>Also: “&lt;value&gt;.png” | Rename one of the PNG basenames so each atlas region has one name. |
6922
+ | <a id="CE_COMPILE_REGION_FILE_CONFLICT"></a>`CE_COMPILE_REGION_FILE_CONFLICT` | “&lt;value&gt;: "&lt;value&gt;" and the art already atlased as region "&lt;value&gt;" are two different files — &lt;value&gt; and &lt;value&gt;. An atlas region is named by its PNG's basename, so only one of the two can hold that name and this attachment would draw the other file's pixels. Rename one of the PNGs.”<br>Also: “skin "&lt;value&gt;" slot "&lt;value&gt;" attachment "&lt;value&gt;"” | Rename one PNG so each region basename denotes exactly one file. |
6923
+ | <a id="CE_COMPILE_SEQUENCE_FRAME_PNG_MISSING"></a>`CE_COMPILE_SEQUENCE_FRAME_PNG_MISSING` | “&lt;value&gt;: sequence &lt;value&gt; is the region "&lt;value&gt;", and there is no PNG for it at &lt;value&gt;. A sequence's frames are the regions "&lt;stem&gt;&lt;start + i&gt;", zero-padded to "digits" — here stem &lt;value&gt;, start &lt;value&gt;, digits &lt;value&gt; — and the compiler draws no frame in place of another. Add the file, or state the "count" the series really has.”<br>Also: “skin "&lt;value&gt;" slot "&lt;value&gt;" attachment "&lt;value&gt;"”<br>“frame &lt;value&gt; of &lt;value&gt; (number &lt;value&gt;)” | Supply the series PNG or correct its stem/start/digits/count. |
6924
+ | <a id="CE_COMPILE_SEQUENCE_FRAME_REGION_MISSING"></a>`CE_COMPILE_SEQUENCE_FRAME_REGION_MISSING` | “&lt;value&gt;: sequence &lt;value&gt; is the region "&lt;value&gt;", which the atlas at &lt;value&gt; does not have. [Did you mean &lt;value&gt;? / ]A sequence's frames are the regions "&lt;stem&gt;&lt;start + i&gt;", zero-padded to "digits" — here stem &lt;value&gt;, start &lt;value&gt;, digits &lt;value&gt; — and the compiler draws no frame in place of another.”<br>Also: “skin "&lt;value&gt;" slot "&lt;value&gt;" attachment "&lt;value&gt;"”<br>“frame &lt;value&gt; of &lt;value&gt; (number &lt;value&gt;)” | Add the series region to the pack or correct its stem/start/digits/count. |
6925
+ | <a id="CE_COMPILE_SEQUENCE_FRAME_FILE_CONFLICT"></a>`CE_COMPILE_SEQUENCE_FRAME_FILE_CONFLICT` | “&lt;value&gt;: sequence &lt;value&gt; is the region "&lt;value&gt;", and the art already atlased under that name is &lt;value&gt;, not &lt;value&gt;. One region name is one set of pixels, so this frame would draw the other file's. Rename one of them.”<br>Also: “skin "&lt;value&gt;" slot "&lt;value&gt;" attachment "&lt;value&gt;"”<br>“frame &lt;value&gt; of &lt;value&gt; (number &lt;value&gt;)” | Rename the conflicting file so one series region denotes one set of pixels. |
6926
+ | <a id="CE_COMPILE_MANIFEST_SLOT_UNKNOWN"></a>`CE_COMPILE_MANIFEST_SLOT_UNKNOWN` | “the manifest binds a part to slot "&lt;value&gt;" (via rig_slot), which the rig "&lt;value&gt;" does not declare — add the slot to the rig rather than inventing one here” | Declare the manifest's rig_slot in the rig's slots array. |
6927
+ | <a id="CE_COMPILE_MANIFEST_DRAW_ORDER_MISMATCH"></a>`CE_COMPILE_MANIFEST_DRAW_ORDER_MISMATCH` | “the manifest draws "&lt;value&gt;" (draw_order &lt;value&gt;) out of the rig's slot order; the rig's slots array IS the draw order” | Make manifest draw_order agree with the rig slots array's order. |
6928
+ | <a id="CE_COMPILE_MANIFEST_MESH_SLOT_BUDGET"></a>`CE_COMPILE_MANIFEST_MESH_SLOT_BUDGET` | “&lt;value&gt; mesh slot(s) declared but the rig "&lt;value&gt;" allows &lt;value&gt; — raise `invariants.meshSlots` in the rig spec if that budget is the thing being changed” | Reduce manifest mesh slots or raise invariants.meshSlots to the intended budget. |
6929
+ | <a id="CE_COMPILE_BASE_PLATE_MESH"></a>`CE_COMPILE_BASE_PLATE_MESH` | “slot "&lt;value&gt;" is the base plate; it must never be a mesh” | Keep the base plate a region attachment. |
6930
+ | <a id="CE_COMPILE_RING_POLYGON_MISSING"></a>`CE_COMPILE_RING_POLYGON_MISSING` | “slot "&lt;value&gt;" declares a ring mesh but has no polygon to use as its rim” | Supply the measured polygon used as the ring rim. |
6931
+ | <a id="CE_COMPILE_RING_HULL_INVALID"></a>`CE_COMPILE_RING_HULL_INVALID` | “slot "&lt;value&gt;": mesh.hull must be "polygon", got &lt;value&gt;” | Set mesh.hull to polygon. |
6932
+ | <a id="CE_COMPILE_RING_PARAMETERS_MISSING"></a>`CE_COMPILE_RING_PARAMETERS_MISSING` | “slot "&lt;value&gt;": a ring mesh needs mesh.center and mesh.inner” | State mesh.center and mesh.inner. |
6933
+ | <a id="CE_COMPILE_RIBBON_PARAMETERS_MISSING"></a>`CE_COMPILE_RIBBON_PARAMETERS_MISSING` | “slot "&lt;value&gt;": a ribbon mesh needs mesh.rows and a mesh.chain” | State mesh.rows and mesh.chain. |
6934
+ | <a id="CE_COMPILE_MESH_CONTROL_BONE_MISSING"></a>`CE_COMPILE_MESH_CONTROL_BONE_MISSING` | “slot "&lt;value&gt;": a mesh with no control bone deforms nothing” | Name at least one control bone for the generated mesh. |
6935
+ | <a id="CE_COMPILE_MANIFEST_WINDOW_SIZE_MISMATCH"></a>`CE_COMPILE_MANIFEST_WINDOW_SIZE_MISMATCH` | “&lt;value&gt; is &lt;value&gt;x&lt;value&gt; but the manifest window for "&lt;value&gt;" is &lt;value&gt;x&lt;value&gt;”<br>Also: “{&lt;value&gt; / region "&lt;value&gt;" of &lt;value&gt; (declared &lt;value&gt;x&lt;value&gt; by its offsets&lt;value&gt;)}”<br>“{ / , at scale: &lt;value&gt;}” | Make the manifest window dimensions agree with the measured image. |
6936
+ | <a id="CE_COMPILE_SLOT_IMAGE_SIZE_MISMATCH"></a>`CE_COMPILE_SLOT_IMAGE_SIZE_MISMATCH` | “&lt;value&gt; is &lt;value&gt;x&lt;value&gt; but slot "&lt;value&gt;" declares &lt;value&gt;x&lt;value&gt;”<br>Also: “{&lt;value&gt; / region "&lt;value&gt;" of &lt;value&gt; (declared &lt;value&gt;x&lt;value&gt; by its offsets&lt;value&gt;)}”<br>“{ / , at scale: &lt;value&gt;}” | Make the rig slot dimensions agree with the measured image. |
6937
+ | <a id="CE_COMPILE_SKIN_SLOT_UNKNOWN"></a>`CE_COMPILE_SKIN_SLOT_UNKNOWN` | “rig skin "&lt;value&gt;" gives attachments to slot "&lt;value&gt;", which the rig does not declare” | Declare the skin's slot in the rig slots array. |
6938
+ | <a id="CE_COMPILE_SLOT_ATTACHMENT_SOURCES_CONFLICT"></a>`CE_COMPILE_SLOT_ATTACHMENT_SOURCES_CONFLICT` | “slot "&lt;value&gt;" is filled by a manifest part AND by rig skin "&lt;value&gt;"; one slot, one source of attachments” | Give this slot attachments from either the manifest or the rig skin. |
6939
+ | <a id="CE_COMPILE_SETUP_TRANSFORM_INVALID"></a>`CE_COMPILE_SETUP_TRANSFORM_INVALID` | “bone "&lt;value&gt;" inherit is &lt;value&gt;, which the runtime resolves to no mode”<br>“bone "&lt;value&gt;" names parent "&lt;value&gt;", which is not declared before it”<br>Also: “bone "&lt;value&gt;": parent "&lt;value&gt;" is not posed before it”<br>“bone "&lt;value&gt;": inheritMode &lt;value&gt; is no mode (readModel refuses it first)” | Correct the bone hierarchy, inherit mode or singular setup transform as the full underlying message states. |
6940
+ | <a id="CE_COMPILE_CONTROL_BONE_UNKNOWN"></a>`CE_COMPILE_CONTROL_BONE_UNKNOWN` | “slot "&lt;value&gt;" drives control bone "&lt;value&gt;", which the rig "&lt;value&gt;" does not declare” | Declare the mesh control bone in the rig. |
6941
+ | <a id="CE_COMPILE_SETUP_ATTACHMENT_AUTHORS_CONFLICT"></a>`CE_COMPILE_SETUP_ATTACHMENT_AUTHORS_CONFLICT` | “slot "&lt;value&gt;" has a setup attachment in the rig spec AND in the motion spec; the setup pose has one author” | Choose the rig slot or motion setup table as this setup attachment's author. |
6942
+ | <a id="CE_COMPILE_SETUP_ATTACHMENT_MISSING"></a>`CE_COMPILE_SETUP_ATTACHMENT_MISSING` | “no setup pose for slot "&lt;value&gt;": give the motion spec a `setup` entry or the rig slot an `attachment` — the compiler will not guess one” | State the slot attachment in the rig or its setup entry in the motion spec. |
6943
+ | <a id="CE_COMPILE_SETUP_ATTACHMENT_UNAVAILABLE"></a>`CE_COMPILE_SETUP_ATTACHMENT_UNAVAILABLE` | “[[restore the files / restore the file] / [add the regions to the pack / add the region to the pack]]”<br>“no region "&lt;value&gt;" in &lt;value&gt;”<br>“setup attachment "&lt;value&gt;" for slot "&lt;value&gt;" is not one of [&lt;value&gt;]”<br>“the setup pose shows attachment "&lt;value&gt;" on slot "&lt;value&gt;", and the slot is emitted empty because [all &lt;value&gt; manifest states that fill it have / the one manifest state that fills it has] no art: &lt;value&gt; — &lt;value&gt;, [fix the paths / fix the path] in the manifest, or state the setup pose as null”<br>“the setup pose shows attachment "&lt;value&gt;" on slot "&lt;value&gt;", which no skin and no manifest part fills — the slot is emitted empty, so there is no such attachment to show. Give the slot an attachment, or state the setup pose as null”<br>Also: “"&lt;value&gt;" (&lt;value&gt;)”<br>“no PNG at &lt;value&gt;” | Select an available attachment, restore the missing manifest art or atlas regions as named, or state setup null. |
6944
+ | <a id="CE_COMPILE_SETUP_COLOUR_AUTHORS_CONFLICT"></a>`CE_COMPILE_SETUP_COLOUR_AUTHORS_CONFLICT` | “slot "&lt;value&gt;" has a setup colour in the rig spec AND in the motion spec” | State the setup colour in either the rig or motion spec. |
6945
+ | <a id="CE_COMPILE_INTERNAL_ATTACHMENT_IMAGE_MISSING"></a>`CE_COMPILE_INTERNAL_ATTACHMENT_IMAGE_MISSING` | “internal: no image for attachment &lt;value&gt;” | Report the attachment name and compiler defect: a resolved attachment lost its image. |
6946
+ | <a id="CE_COMPILE_GENERATED_MESH_SLOT_BUDGET"></a>`CE_COMPILE_GENERATED_MESH_SLOT_BUDGET` | “&lt;value&gt; mesh slot(s) emitted but the rig "&lt;value&gt;" allows &lt;value&gt;[ — a mesh rigc GENERATED counts against `invariants.meshSlots`, and this rig declares none, which is a budget of 0. Add `"invariants": { "meshSlots": &lt;value&gt;, "meshTriangles": &lt;triangles one mesh may carry&gt; }` to the rig spec: geometry rigc built is geometry it will not ship unmeasured, and `A13_MESH_BUDGET` has nothing to measure against until that budget is stated. (Authored geometry is exempt — rigc did not draw it.) / — raise `invariants.meshSlots` in the rig spec if that budget is the thing being changed]” | Declare or raise invariants.meshSlots and meshTriangles to measure generated geometry, or reduce generated meshes. |
6947
+ | <a id="CE_COMPILE_PHYSICS_NAME_RESERVED"></a>`CE_COMPILE_PHYSICS_NAME_RESERVED` | “physics constraint "&lt;value&gt;": the name is reserved — a motion spec's `"physics": "&lt;value&gt;"` is the timeline that names no constraint and drives every physics constraint declaring the keyed property global, so a constraint called that could not be keyed by name. Rename it”<br>Here the values named in the message include: “*”. | Rename the physics constraint; the reserved global target names no constraint. |
6948
+ | <a id="CE_COMPILE_PHYSICS_DECLARATION_DUPLICATE"></a>`CE_COMPILE_PHYSICS_DECLARATION_DUPLICATE` | “physics constraint "&lt;value&gt;" is declared in both the rig spec and the motion spec's physics table” | Declare this physics constraint in either the rig or motion physics table. |
6949
+ | <a id="CE_COMPILE_PHYSICS_BONE_UNKNOWN"></a>`CE_COMPILE_PHYSICS_BONE_UNKNOWN` | “physics constraint "&lt;value&gt;" targets unknown bone "&lt;value&gt;"” | Declare the physics target bone or correct its name. |
6950
+ | <a id="CE_COMPILE_PHYSICS_STOP_ORDER_INVALID"></a>`CE_COMPILE_PHYSICS_STOP_ORDER_INVALID` | “physics constraint "&lt;value&gt;" drives "&lt;value&gt;", a link stop "&lt;value&gt;" holds, from the physics table — the table is emitted after every rig constraint, past the stop's copy and clamp, which would read the link before this swings it; declare the constraint in the rig spec's "constraints"” | Declare the physics constraint in rig constraints so it runs before the stop's copy and clamp. |
6951
+ | <a id="CE_COMPILE_PHYSICS_COMPONENTS_EMPTY"></a>`CE_COMPILE_PHYSICS_COMPONENTS_EMPTY` | “physics constraint "&lt;value&gt;" drives no component — set at least one of &lt;value&gt;”<br>Here the values named in the message include: “/”, “x”, “scaleX”, “rotate”, “shearX”. | Enable at least one physics component named in the message. |
6952
+ | <a id="CE_COMPILE_PHYSICS_GLOBAL_GROUP_MEMBER"></a>`CE_COMPILE_PHYSICS_GLOBAL_GROUP_MEMBER` | “animation "&lt;value&gt;": group "&lt;value&gt;" lists "&lt;value&gt;", which is not a constraint but the target that names none — write it as the track's `"physics": "&lt;value&gt;"`”<br>Here the values named in the message include: “*”. | Write the reserved target directly as the track's physics field. |
6953
+ | <a id="CE_COMPILE_PHYSICS_GLOBAL_TRACK_INERT"></a>`CE_COMPILE_PHYSICS_GLOBAL_TRACK_INERT` | “animation "&lt;value&gt;" keys physics "&lt;value&gt;" &lt;value&gt;, the timeline that names no constraint and drives every physics constraint [the rig has / declaring "&lt;value&gt;": true], and [the rig declares no physics constraint / none of &lt;value&gt; does] — it would parse and move nothing. [Declare a physics constraint, or remove the track / Set "&lt;value&gt;": true on the constraints it is for, or key one by name]”<br>Also: “&lt;value&gt;Global”<br>Here the values named in the message include: “*”, “motion”. | Declare physics constraints and the named global flags, or target one constraint by name; remove an unused track. |
6954
+ | <a id="CE_COMPILE_CONSTRAINT_TRACK_TYPE_MISMATCH"></a>`CE_COMPILE_CONSTRAINT_TRACK_TYPE_MISMATCH` | “animation "&lt;value&gt;" keys "&lt;value&gt;" as a &lt;value&gt;, but the rig declares it as a "&lt;value&gt;" constraint — a timeline group resolves its target by name AND type, misses, and the loader throws”<br>Here the values named in the message include: “"/"”. | Use the timeline family matching the declared constraint type. |
6955
+ | <a id="CE_COMPILE_CONSTRAINT_TRACK_TARGET_UNKNOWN"></a>`CE_COMPILE_CONSTRAINT_TRACK_TARGET_UNKNOWN` | “animation "&lt;value&gt;" keys unknown &lt;value&gt; "&lt;value&gt;"[ (the rig declares: &lt;value&gt;) / , and the rig declares no &lt;value&gt; constraint at all]”<br>Here the values named in the message include: “physics”. | Use a declared constraint name of the required timeline family. |
6956
+ | <a id="CE_COMPILE_ANIMATION_BONE_UNKNOWN"></a>`CE_COMPILE_ANIMATION_BONE_UNKNOWN` | “animation "&lt;value&gt;" keys unknown bone "&lt;value&gt;"” | Declare or correct the keyed bone name. |
6957
+ | <a id="CE_COMPILE_ANIMATION_SLOT_UNKNOWN"></a>`CE_COMPILE_ANIMATION_SLOT_UNKNOWN` | “animation "&lt;value&gt;" targets unknown slot "&lt;value&gt;"” | Declare or correct the target slot name. |
6958
+ | <a id="CE_COMPILE_ANIMATION_TRACK_DUPLICATE"></a>`CE_COMPILE_ANIMATION_TRACK_DUPLICATE` | “animation "&lt;value&gt;" has two tracks on &lt;value&gt;.&lt;value&gt;; merge them into one track” | Merge the tracks on this target and property into one. |
6959
+ | <a id="CE_COMPILE_COLOUR_TRACK_CHANNEL_OVERLAP"></a>`CE_COMPILE_COLOUR_TRACK_CHANNEL_OVERLAP` | “alpha”<br>“animation "&lt;value&gt;" slot "&lt;value&gt;": tracks "&lt;value&gt;" and "&lt;value&gt;" both key the slot's &lt;value&gt; — a colour timeline poses its channels at every time, its setup value before its first key included, so the one the file states later overwrites the other everywhere and the first one's keys there are read by nothing. Key each channel once: "rgb" and "alpha" move the light colour's two halves on their own key times, "rgba" moves them together, and "rgb2" / "rgba2" add the dark colour”<br>“dark colour”<br>“light rgb” | Key each colour channel once using rgb/alpha, rgba or the dark colour forms as stated. |
6960
+ | <a id="CE_COMPILE_CONSTRAINT_TIMELINE_TYPE_MISMATCH"></a>`CE_COMPILE_CONSTRAINT_TIMELINE_TYPE_MISMATCH` | “animation "&lt;value&gt;" keys "&lt;value&gt;" as [an / a] &lt;value&gt; constraint, but the rig declares it as a "&lt;value&gt;" constraint — the parser looks a timeline's target up by name AND type, misses, and throws”<br>Here the values named in the message include: “"/"”. | Choose the timeline family matching this rig constraint's type. |
6961
+ | <a id="CE_COMPILE_CONSTRAINT_TIMELINE_TARGET_UNKNOWN"></a>`CE_COMPILE_CONSTRAINT_TIMELINE_TARGET_UNKNOWN` | “animation "&lt;value&gt;" keys unknown &lt;value&gt; constraint "&lt;value&gt;"; [the rig declares &lt;value&gt; constraint(s): &lt;value&gt; / the rig declares no &lt;value&gt; constraint at all]”<br>Also: “, ” | Use a declared constraint name of the required group. |
6962
+ | <a id="CE_COMPILE_CONSTRAINT_TIMELINE_DUPLICATE"></a>`CE_COMPILE_CONSTRAINT_TIMELINE_DUPLICATE` | “animation "&lt;value&gt;" has two &lt;value&gt; timelines on constraint "&lt;value&gt;"; the group holds one timeline per constraint, so merge them into one” | Merge the group's timelines on this constraint into one. |
6963
+ | <a id="CE_COMPILE_ATTACHMENT_TIMELINE_SKIN_UNKNOWN"></a>`CE_COMPILE_ATTACHMENT_TIMELINE_SKIN_UNKNOWN` | “&lt;value&gt;: this rig emits no skin called "&lt;value&gt;" (it emits: &lt;value&gt;)”<br>Also: “animation "&lt;value&gt;" deform &lt;value&gt;/&lt;value&gt;/&lt;value&gt;”<br>“, ”<br>“animation "&lt;value&gt;" sequence &lt;value&gt;/&lt;value&gt;/&lt;value&gt;”<br>Here the values named in the message include: “default”. | Target an emitted skin name. |
6964
+ | <a id="CE_COMPILE_ATTACHMENT_TIMELINE_SLOT_EMPTY"></a>`CE_COMPILE_ATTACHMENT_TIMELINE_SLOT_EMPTY` | “&lt;value&gt;: skin "&lt;value&gt;" gives slot "&lt;value&gt;" no attachments[ / , and this rig does not declare that slot at all]”<br>Also: “animation "&lt;value&gt;" deform &lt;value&gt;/&lt;value&gt;/&lt;value&gt;”<br>“animation "&lt;value&gt;" sequence &lt;value&gt;/&lt;value&gt;/&lt;value&gt;”<br>Here the values named in the message include: “default”. | Target a declared slot with attachments in the chosen skin. |
6965
+ | <a id="CE_COMPILE_ATTACHMENT_TIMELINE_ATTACHMENT_UNKNOWN"></a>`CE_COMPILE_ATTACHMENT_TIMELINE_ATTACHMENT_UNKNOWN` | “&lt;value&gt;: slot "&lt;value&gt;" in skin "&lt;value&gt;" has no attachment "&lt;value&gt;" (it has: &lt;value&gt;)”<br>Also: “animation "&lt;value&gt;" deform &lt;value&gt;/&lt;value&gt;/&lt;value&gt;”<br>“, ”<br>“animation "&lt;value&gt;" sequence &lt;value&gt;/&lt;value&gt;/&lt;value&gt;”<br>Here the values named in the message include: “default”. | Target an attachment placeholder present in the chosen skin and slot. |
6966
+ | <a id="CE_COMPILE_DEFORM_TIMELINE_DUPLICATE"></a>`CE_COMPILE_DEFORM_TIMELINE_DUPLICATE` | “&lt;value&gt;: two deform timelines on one attachment; merge them into one”<br>Also: “animation "&lt;value&gt;" deform &lt;value&gt;/&lt;value&gt;/&lt;value&gt;”<br>“animation "&lt;value&gt;" sequence &lt;value&gt;/&lt;value&gt;/&lt;value&gt;”<br>Here the values named in the message include: “default”. | Merge deform timelines on this attachment into one. |
6967
+ | <a id="CE_COMPILE_SEQUENCE_TIMELINE_DUPLICATE"></a>`CE_COMPILE_SEQUENCE_TIMELINE_DUPLICATE` | “&lt;value&gt;: two sequence timelines on one attachment; merge them into one”<br>Also: “animation "&lt;value&gt;" deform &lt;value&gt;/&lt;value&gt;/&lt;value&gt;”<br>“animation "&lt;value&gt;" sequence &lt;value&gt;/&lt;value&gt;/&lt;value&gt;”<br>Here the values named in the message include: “default”. | Merge sequence timelines on this attachment into one. |
6968
+ | <a id="CE_COMPILE_ANIMATION_DURATION_MISMATCH"></a>`CE_COMPILE_ANIMATION_DURATION_MISMATCH` | “animation "&lt;value&gt;" declares duration &lt;value&gt;s but its last key is at &lt;value&gt;s” | Make the declared duration match the last compiled key time. |
6969
+ | <a id="CE_COMPILE_SLOT_BONE_MISSING"></a>`CE_COMPILE_SLOT_BONE_MISSING` | “slot "&lt;value&gt;" has no bone” | Give the slot a declared bone. |
6970
+
6971
+
6972
+ #### 5.1.4 Bones and skin placeholders
6973
+
6974
+ | Code | Fixed message text and alternatives | What to change |
6975
+ | --- | --- | --- |
6976
+ | <a id="CE_COMPILE_BONE_PARENT_ORDER"></a>`CE_COMPILE_BONE_PARENT_ORDER` | “bone "&lt;value&gt;" names parent "&lt;value&gt;", which is declared after it” | Declare the parent before its child. |
6977
+ | <a id="CE_COMPILE_BONE_POSITION_MANIFEST_REQUIRED"></a>`CE_COMPILE_BONE_POSITION_MANIFEST_REQUIRED` | “bone "&lt;value&gt;" takes its position from &lt;value&gt;, which needs a cut manifest”<br>Also: “the window of slot "&lt;value&gt;"”<br>“the manifest anchor "&lt;value&gt;"”<br>“the mesh centre of slot "&lt;value&gt;"” | Supply the cut manifest needed by this measured bone position source. |
6978
+ | <a id="CE_COMPILE_BONE_ANCHOR_MISSING"></a>`CE_COMPILE_BONE_ANCHOR_MISSING` | “manifest anchors has no [x, y] for "&lt;value&gt;" (bone "&lt;value&gt;" of rig "&lt;value&gt;")” | Supply the named manifest anchor as an x/y pair. |
6979
+ | <a id="CE_COMPILE_BONE_SLOT_WINDOW_MISSING"></a>`CE_COMPILE_BONE_SLOT_WINDOW_MISSING` | “bone "&lt;value&gt;" sits at the centre of slot "&lt;value&gt;", which this cut's manifest carries no part for” | Supply the manifest part whose window positions this bone. |
6980
+ | <a id="CE_COMPILE_BONE_MESH_CENTER_MISSING"></a>`CE_COMPILE_BONE_MESH_CENTER_MISSING` | “bone "&lt;value&gt;" sits on the mesh centre of slot "&lt;value&gt;", which declares no mesh.center” | Declare mesh.center for the slot used to position this bone. |
6981
+ | <a id="CE_COMPILE_BONE_ROTATION_AXIS_MISSING"></a>`CE_COMPILE_BONE_ROTATION_AXIS_MISSING` | “bone "&lt;value&gt;" takes its rotation from the cut axis, which the manifest does not declare” | Declare the cut axis in the manifest. |
6982
+ | <a id="CE_COMPILE_BONE_ANCHOR_ROTATION_MISSING"></a>`CE_COMPILE_BONE_ANCHOR_ROTATION_MISSING` | “bone "&lt;value&gt;" takes its rotation from anchor "&lt;value&gt;", which has no third element (a screen-space facing angle)” | Supply the anchor's third element as a screen-space facing angle. |
6983
+ | <a id="CE_COMPILE_DEFAULT_SKIN_PLACEHOLDER_CONFLICT"></a>`CE_COMPILE_DEFAULT_SKIN_PLACEHOLDER_CONFLICT` | “slot "&lt;value&gt;": placeholder "&lt;value&gt;" is filled by the "&lt;value&gt;" skin AND by [skin / skins] &lt;value&gt;, and the Spine editor has no way to hold that. Measured on 4.3.26 in both spellings: give the default skin's attachment a name of its own and the editor re-keys it by that name on export, so the slot's setup attachment "&lt;value&gt;" resolves in no default-skin key and the default skin draws nothing; leave it as the placeholder and the import is refused outright with "Multiple attachments have the same name: &lt;value&gt; &lt;value&gt;", because a default-skin attachment hangs on the slot beside the named skins' placeholder of that name. Move the default skin's entry for this slot into a named skin — call it "base" — so every skin filling "&lt;value&gt;" is a named one. Two or more named skins sharing a placeholder is the shape the editor exports itself, and it needs no `name` (#796).” | Move this default-skin slot entry into a named skin so every skin filling the placeholder is named. |
6984
+
6985
+
6986
+ #### 5.1.5 Attachments, polygons and paths
6987
+
6988
+ | Code | Fixed message text and alternatives | What to change |
6989
+ | --- | --- | --- |
6990
+ | <a id="CE_COMPILE_ATTACHMENT_TYPE_NOT_NAME"></a>`CE_COMPILE_ATTACHMENT_TYPE_NOT_NAME` | “&lt;value&gt;: "type" is &lt;value&gt;, which is not a name. An attachment's type is one of &lt;value&gt;, or the key is absent and reads as "region". PRESENT-and-null is not absent: `getValue(map, "type", "region")` takes the default only when the key is missing (`SkeletonJson.ts:527`), so this map matches no case, `readAttachment` returns null (`:653`), and the attachment is dropped from the skeleton without a word. Remove the key, or name a type.”<br>Here the values named in the message include: “linkedmesh”, “path”, “point”, “clipping”, “boundingbox”. | Name an attachment type or omit the type key for region; present null is refused. |
6991
+ | <a id="CE_COMPILE_ATTACHMENT_NAME_NOT_STRING"></a>`CE_COMPILE_ATTACHMENT_NAME_NOT_STRING` | “&lt;value&gt;: "name" is &lt;value&gt;, which is not a string. An attachment's name is the runtime's `Attachment.name` — `getValue(map, "name", placeholder)`, `SkeletonJson.js:526` — and on a region, mesh or linked mesh it is also what `path` defaults to. Write it as a string, or leave the key out and the attachment is named by its placeholder.” | Use a string name or omit name to use the placeholder. |
6992
+ | <a id="CE_COMPILE_ATTACHMENT_TYPE_DEFERRED"></a>`CE_COMPILE_ATTACHMENT_TYPE_DEFERRED` | “&lt;value&gt;: this attachment is a "&lt;value&gt;"&lt;value&gt; — &lt;value&gt;. rigc does not emit it yet, deliberately: it emits &lt;value&gt;, and a point appears nowhere in the benchmark corpus, so it is not on the ladder's critical path. docs/SPEC_COVERAGE.md part 1-6 is the row this sentence reads from, and it is what an implementation would have to carry.”<br>“a position and an angle with no geometry at all — "x", "y", "rotation" and "color", posed by its bone and drawn by nothing; what reads it is game code asking where a muzzle or a hand is”<br>Here the values named in the message include: “linkedmesh”, “region”, “clipping”, “boundingbox”. | Use an emitted attachment type or implement the unsupported format type with its own measured gate. |
6993
+ | <a id="CE_COMPILE_ATTACHMENT_TYPE_UNKNOWN"></a>`CE_COMPILE_ATTACHMENT_TYPE_UNKNOWN` | “&lt;value&gt;: attachment type "&lt;value&gt;" is not one of the &lt;value&gt; the Spine 4.3 format defines (&lt;value&gt;). [Did you mean &lt;value&gt;? / ]The parser matches no case for it, `readAttachment` returns null (`SkeletonJson.ts:653`), and the attachment is dropped from the skeleton without a word.[ "sequence" is a KEY on a region or a mesh rather than a type of its own (docs/SPEC_COVERAGE.md part 1-6). / ]”<br>Here the values named in the message include: “path”, “point”, “clipping”, “linkedmesh”, “boundingbox”. | Use a Spine 4.3 attachment type; sequence is a key on region/mesh, rather than a type. |
6994
+ | <a id="CE_COMPILE_POLYGON_VERTEX_COUNT_INVALID"></a>`CE_COMPILE_POLYGON_VERTEX_COUNT_INVALID` | “&lt;value&gt;: vertexCount is &lt;value&gt;; a polygon needs at least 3 vertices, stated outright — the field has no parser default, and an absent one reads as 0 and takes the polygon with it” | State an integer vertexCount of at least three for the polygon. |
6995
+ | <a id="CE_COMPILE_VERTEX_GEOMETRY_SOURCES_CONFLICT"></a>`CE_COMPILE_VERTEX_GEOMETRY_SOURCES_CONFLICT` | “&lt;value&gt;: geometry comes as "vertices" or as "weights", never both — "weights" is the by-name form of the same data” | Supply vertices or by-name weights, rather than both. |
6996
+ | <a id="CE_COMPILE_NAMED_WEIGHTS_RAW_INDEXING"></a>`CE_COMPILE_NAMED_WEIGHTS_RAW_INDEXING` | “&lt;value&gt;: "boneIndexing": "raw" describes a "vertices" run; "weights" always binds by name” | Remove boneIndexing raw from by-name weights; raw describes a vertices run. |
6997
+ | <a id="CE_COMPILE_POLYGON_WEIGHT_VERTEX_COUNT"></a>`CE_COMPILE_POLYGON_WEIGHT_VERTEX_COUNT` | “&lt;value&gt;: weights cover &lt;value&gt; vertices but vertexCount is &lt;value&gt;” | Make the weights vertex count agree with vertexCount. |
6998
+ | <a id="CE_COMPILE_POLYGON_GEOMETRY_MISSING"></a>`CE_COMPILE_POLYGON_GEOMETRY_MISSING` | “&lt;value&gt;: needs geometry — "vertices" (x, y per vertex) or "weights" (bound by name)” | Supply vertices or by-name weights. |
6999
+ | <a id="CE_COMPILE_POLYGON_WEIGHTED_RUN_IMPLICIT"></a>`CE_COMPILE_POLYGON_WEIGHTED_RUN_IMPLICIT` | “&lt;value&gt;: vertexCount &lt;value&gt; wants &lt;value&gt; unweighted numbers and "vertices" holds &lt;value&gt;. The parser reads that as a WEIGHTED run, whose bone INDEXES point into the emitted bone array — a list the spec never writes, so inserting a bone rebinds every vertex in silence. Give the bindings by name as "weights": [[{ "bone": …, "x": …, "y": …, "weight": … }, …], …], fix vertexCount, or say "boneIndexing": "raw" on this attachment to keep the index form deliberately.” | Use by-name weights, correct vertexCount, or request raw bone indexing deliberately. |
7000
+ | <a id="CE_COMPILE_VERTEX_VALUE_NONFINITE"></a>`CE_COMPILE_VERTEX_VALUE_NONFINITE` | “&lt;value&gt;: the vertex array holds a non-finite value &lt;value&gt;” | Supply finite numbers in the vertices array. |
7001
+ | <a id="CE_COMPILE_RAW_WEIGHT_BONE_COUNT_INVALID"></a>`CE_COMPILE_RAW_WEIGHT_BONE_COUNT_INVALID` | “&lt;value&gt;: the raw weighted run has a bone count of &lt;value&gt; at index &lt;value&gt;” | Write a valid bone count for every raw weighted vertex. |
7002
+ | <a id="CE_COMPILE_RAW_WEIGHT_RUN_TRUNCATED"></a>`CE_COMPILE_RAW_WEIGHT_RUN_TRUNCATED` | “&lt;value&gt;: the raw weighted run is truncated — vertex &lt;value&gt; claims &lt;value&gt; bone(s) and the array ends first” | Supply every bone index/x/y/weight tuple claimed by the raw run. |
7003
+ | <a id="CE_COMPILE_RAW_WEIGHT_VERTEX_COUNT_MISMATCH"></a>`CE_COMPILE_RAW_WEIGHT_VERTEX_COUNT_MISMATCH` | “&lt;value&gt;: the raw weighted run decodes to &lt;value&gt; vertices but &lt;value&gt;”<br>“there are &lt;value&gt; uv pairs”<br>“vertexCount is &lt;value&gt;” | Make the decoded raw run vertex count match its declared geometry. |
7004
+ | <a id="CE_COMPILE_RAW_WEIGHT_BONE_INDEX_UNKNOWN"></a>`CE_COMPILE_RAW_WEIGHT_BONE_INDEX_UNKNOWN` | “&lt;value&gt;: vertex &lt;value&gt; binds bone index &lt;value&gt;, which is not in the bone list” | Use a bone index present in the emitted bone list, or author by-name weights. |
7005
+ | <a id="CE_COMPILE_STAGE_BOX_STAGE_MISSING"></a>`CE_COMPILE_STAGE_BOX_STAGE_MISSING` | “&lt;value&gt;: the rig declares no stage, so there is no box to write — state skeleton.width and skeleton.height”<br>Also: “skeleton.stageBox (slot "&lt;value&gt;", attachment "&lt;value&gt;")” | State skeleton.width and skeleton.height before requesting a stage box. |
7006
+ | <a id="CE_COMPILE_STAGE_BOX_SLOT_UNKNOWN"></a>`CE_COMPILE_STAGE_BOX_SLOT_UNKNOWN` | “&lt;value&gt;: slot "&lt;value&gt;" is not one the rig declares. Declare it in "slots" — where it stands in the array is its place in the draw order, and its "bone" is the box's bone — e.g. { "name": "&lt;value&gt;", "bone": "root", "attachment": "&lt;value&gt;" }”<br>Also: “skeleton.stageBox (slot "&lt;value&gt;", attachment "&lt;value&gt;")” | Declare a dedicated stage-box slot in the rig's slots array. |
7007
+ | <a id="CE_COMPILE_STAGE_BOX_SLOT_CONFLICT"></a>`CE_COMPILE_STAGE_BOX_SLOT_CONFLICT` | “&lt;value&gt;: slot "&lt;value&gt;" is also filled by &lt;value&gt;. The stage box is its slot's one attachment, so a reader of that slot finds the stage and nothing else: give the box a slot of its own”<br>Also: “skeleton.stageBox (slot "&lt;value&gt;", attachment "&lt;value&gt;")”<br>“the attachment(s) [&lt;value&gt;]”<br>“a cut manifest part” | Give the stage box a slot of its own. |
7008
+ | <a id="CE_COMPILE_STAGE_BOX_BONE_UNKNOWN"></a>`CE_COMPILE_STAGE_BOX_BONE_UNKNOWN` | “&lt;value&gt;: slot "&lt;value&gt;" names bone "&lt;value&gt;", which the rig does not declare”<br>Also: “skeleton.stageBox (slot "&lt;value&gt;", attachment "&lt;value&gt;")” | Declare the stage-box slot's bone. |
7009
+ | <a id="CE_COMPILE_STAGE_BOX_BONE_NOT_ROOT"></a>`CE_COMPILE_STAGE_BOX_BONE_NOT_ROOT` | “&lt;value&gt;: slot "&lt;value&gt;" hangs on bone "&lt;value&gt;", which is not the root. The box's vertices are the stage's corners in world space, written as they are, and the gate holds them on the header's grid through the runtime's own frame of an unrotated root; every bone below it adds that frame's residue once more (the runtime spells an unrotated b as cos 90° at its pi, -2.3e-8 per level). Put the slot on the root ("&lt;value&gt;")”<br>Also: “skeleton.stageBox (slot "&lt;value&gt;", attachment "&lt;value&gt;")” | Put the stage-box slot on the untransformed root bone. |
7010
+ | <a id="CE_COMPILE_STAGE_BOX_ROOT_TRANSFORMED"></a>`CE_COMPILE_STAGE_BOX_ROOT_TRANSFORMED` | “&lt;value&gt;: slot "&lt;value&gt;" hangs on the root "&lt;value&gt;", which states a setup transform (&lt;value&gt;). The box's vertices are the stage's corners in world space, written as they are, so the root must not move, turn, scale or shear at setup — move what the root carries onto a bone below it, or drop stageBox”<br>Also: “skeleton.stageBox (slot "&lt;value&gt;", attachment "&lt;value&gt;")”<br>Here the values named in the message include: “scaleY”, “shearY”, “scaleX”, “shearX”, “rotation”. | Move the root's setup transform to a child bone or drop stageBox. |
7011
+ | <a id="CE_COMPILE_CLIPPING_END_SLOT_UNKNOWN"></a>`CE_COMPILE_CLIPPING_END_SLOT_UNKNOWN` | “&lt;value&gt;: end names slot &lt;value&gt;, which this rig does not declare; a miss loads as null and the clip then runs to the bottom of the draw order” | Name a declared end slot or omit the clipping end deliberately. |
7012
+ | <a id="CE_COMPILE_VERTEX_BIND_TRANSFORM_MISSING"></a>`CE_COMPILE_VERTEX_BIND_TRANSFORM_MISSING` | “&lt;value&gt;: vertex &lt;value&gt; binds bone "&lt;value&gt;", which has no setup transform” | Correct the weighted bone name/setup hierarchy; report a missing compiled setup transform for a declared bone. |
7013
+ | <a id="CE_COMPILE_PATH_VERTEX_COUNT_MULTIPLE"></a>`CE_COMPILE_PATH_VERTEX_COUNT_MULTIPLE` | “&lt;value&gt;: vertexCount is &lt;value&gt;, which is not a multiple of 3. A path's vertices are knots AND their Bezier handles, read in groups of three; the parser sizes its lengths array with `vertexCount / 3` and accepts a fractional size without a word, so the curves would straddle the knots.” | State the path's knot/Bezier handle vertices in groups of three. |
7014
+ | <a id="CE_COMPILE_PATH_VERTEX_COUNT_MINIMUM"></a>`CE_COMPILE_PATH_VERTEX_COUNT_MINIMUM` | “&lt;value&gt;: vertexCount is &lt;value&gt; and [a closed / an open] path needs at least &lt;value&gt; — [a closed path of K curves carries 3K points / an open one carries 3(K + 1), the first and last being the end knots' outer handles]” | Supply enough vertices for the stated open or closed path. |
7015
+ | <a id="CE_COMPILE_SLOT_SETUP_TRANSFORM_MISSING"></a>`CE_COMPILE_SLOT_SETUP_TRANSFORM_MISSING` | “&lt;value&gt;: slot bone "&lt;value&gt;" has no setup transform” | Correct the slot bone/setup hierarchy; report a missing compiled transform for a declared bone. |
7016
+ | <a id="CE_COMPILE_PATH_GEOMETRY_LENGTH_INVALID"></a>`CE_COMPILE_PATH_GEOMETRY_LENGTH_INVALID` | “&lt;value&gt;: the geometry measures &lt;value&gt; entry(ies) where the parser sizes &lt;value&gt;, of total length &lt;value&gt;; a path of zero length divides by zero the first time a bone is placed on it” | Supply a nonzero-length path whose measured curve count matches its vertex count. |
7017
+ | <a id="CE_COMPILE_PATH_LENGTHS_NOT_ARRAY"></a>`CE_COMPILE_PATH_LENGTHS_NOT_ARRAY` | “&lt;value&gt;: "lengths" is &lt;value&gt;; it is an array of &lt;value&gt; number(s)” | Supply lengths as the finite cumulative-length array or omit it for measurement. |
7018
+ | <a id="CE_COMPILE_PATH_LENGTHS_COUNT"></a>`CE_COMPILE_PATH_LENGTHS_COUNT` | “&lt;value&gt;: "lengths" has N entry(ies) where the parser sizes M — vertexCount / 3 on [a closed / an open] path[ / , one more than its curves: the editor writes the wrap-around curve's cumulative last and nothing reads it]. Give the array the source states, or leave the field out and rigc measures it”<br>Read the count pair as `"lengths" has N entry(ies) where the parser sizes M — vertexCount / 3 on …`: N is the stated array's length; M is the count the parser allocates from vertexCount / 3. | Make lengths match the count the path vertexCount and closed state require, or omit lengths for measurement. |
7019
+ | <a id="CE_COMPILE_PATH_LENGTH_NONFINITE"></a>`CE_COMPILE_PATH_LENGTH_NONFINITE` | “&lt;value&gt;: "lengths"[&lt;value&gt;] is &lt;value&gt;; every entry is a finite cumulative length” | Supply finite cumulative path lengths. |
7020
+ | <a id="CE_COMPILE_PATH_LENGTHS_DESCENDING"></a>`CE_COMPILE_PATH_LENGTHS_DESCENDING` | “&lt;value&gt;: "lengths"[&lt;value&gt;] is &lt;value&gt;, below [0 / the &lt;value&gt; before it]. The array is CUMULATIVE — the length at the end of each curve — so no entry is below its predecessor” | Make every cumulative path length at least its predecessor and the first at least zero. |
7021
+ | <a id="CE_COMPILE_INTERNAL_IMAGE_NOT_ATLASED"></a>`CE_COMPILE_INTERNAL_IMAGE_NOT_ATLASED` | “&lt;value&gt;: the image "&lt;value&gt;" was never added to the atlas, so there is no region "&lt;value&gt;" for this attachment to draw and no measurement of it to take a size from. Every image an attachment names is measured and atlased — one per file, whichever skin names it (issue #555) — so reaching this means rigc skipped one, not that the spec left anything out. [The nearest region(s) built are &lt;value&gt;. / ]The atlas holds &lt;value&gt; region(s): &lt;value&gt;” | Report this compiler defect with the image and atlas region names; an attachment image was skipped during atlas collection. |
7022
+ | <a id="CE_COMPILE_SEQUENCE_FRAME_SIZE_AMBIGUOUS"></a>`CE_COMPILE_SEQUENCE_FRAME_SIZE_AMBIGUOUS` | “&lt;value&gt;: the &lt;value&gt; frames of this sequence measure &lt;value&gt; in &lt;value&gt; (&lt;value&gt;), and an attachment has one &lt;value&gt; every frame is drawn into. State "&lt;value&gt;" — the frames do not agree on one” | State the attachment dimension named in the message because its frames do not share one size. |
7023
+ | <a id="CE_COMPILE_INTERNAL_SEQUENCE_FRAME_NOT_ATLASED"></a>`CE_COMPILE_INTERNAL_SEQUENCE_FRAME_NOT_ATLASED` | “&lt;value&gt;: sequence frame &lt;value&gt; is the region "&lt;value&gt;", which was never added to the atlas — every frame of a sequence is atlased or refused by name before any attachment is built, so reaching this means rigc skipped one” | Report this compiler defect with the series region name; a series frame was skipped during atlas collection. |
7024
+ | <a id="CE_COMPILE_REGION_ATLAS_SIZE_MISMATCH"></a>`CE_COMPILE_REGION_ATLAS_SIZE_MISMATCH` | “&lt;value&gt;: the spec says &lt;value&gt; &lt;value&gt; and region "&lt;value&gt;" of the imported atlas is &lt;value&gt; (bounds &lt;value&gt;x&lt;value&gt;, offsets state a &lt;value&gt;x&lt;value&gt; drawing[ / in the page's texels, which its scale: &lt;value&gt; makes a &lt;value&gt;x&lt;value&gt; drawing (+/- &lt;value&gt;px, the pack's rounding)])”<br>Here the values named in the message include: “width”, “height”. | Make the stated attachment dimension agree with the imported atlas's measured drawing size and scale. |
7025
+ | <a id="CE_COMPILE_REGION_SIZE_MISSING"></a>`CE_COMPILE_REGION_SIZE_MISSING` | “&lt;value&gt;: a region needs width and height — give them, or give an "image" and rigc will measure the PNG” | State width/height or supply image for PNG measurement. |
7026
+ | <a id="CE_COMPILE_VERTEX_BINDINGS_EMPTY"></a>`CE_COMPILE_VERTEX_BINDINGS_EMPTY` | “&lt;value&gt;: vertex &lt;value&gt; has no bone bindings; a weighted vertex names at least one bone” | Name at least one bone binding on every weighted vertex. |
7027
+ | <a id="CE_COMPILE_VERTEX_BIND_BONE_UNKNOWN"></a>`CE_COMPILE_VERTEX_BIND_BONE_UNKNOWN` | “&lt;value&gt;: vertex &lt;value&gt; binds bone &lt;value&gt;, which the rig does not declare as a bone” | Use bone names declared by the rig in every vertex binding. |
7028
+ | <a id="CE_COMPILE_AUTHORED_MESH_OUTLINE_INVALID"></a>`CE_COMPILE_AUTHORED_MESH_OUTLINE_INVALID` | “ — the triangles are &lt;value&gt; pieces that share no vertex, and one mesh is one outline: `rigc split --rig &lt;rig&gt; --motion &lt;motion&gt; --slot &lt;value&gt; --attachment &lt;value&gt;&lt;value&gt; --out &lt;dir&gt;` writes one mesh per piece, its deform keys renumbered (AUTHORING §3.4.11)”<br>“&lt;value&gt;: &lt;value&gt;&lt;value&gt;”<br>“[ / --skin &lt;value&gt;]”<br>“hull &lt;value&gt; disagrees with the triangles, whose outline has &lt;value&gt; vertices (&lt;value&gt;). Delete "hull" and rigc derives it, or state &lt;value&gt;”<br>“hull vertices must come first; vertex &lt;value&gt; is on the boundary and vertex &lt;value&gt; is not. The triangles' outline runs &lt;value&gt;: list those &lt;value&gt; vertices first, in that order, then the &lt;value&gt; interior vertices”<br>“hull vertices must trace the outline in order; the triangles' outline runs &lt;value&gt;, so vertex &lt;value&gt; has to follow vertex &lt;value&gt; in the list, and vertex &lt;value&gt; does. Renumber the vertices along that walk”<br>“the triangles do not tile the outline: &lt;value&gt; vertices with a &lt;value&gt;-vertex outline tile as &lt;value&gt; triangles and there are &lt;value&gt; — Spine's binary reader derives the triangle count from exactly that, so a mesh that breaks it cannot be read back from a .skel”<br>“the triangles have no outline: every edge is shared by two triangles”<br>“the triangles' outline is not one closed loop: the walk from vertex &lt;value&gt; closes after &lt;value&gt; of &lt;value&gt; boundary vertices”<br>“the triangles' outline is not one closed loop: vertex &lt;value&gt; has &lt;value&gt; boundary edges”<br>“triangle &lt;value&gt; (&lt;value&gt;) repeats a vertex, so it has no area”<br>“triangle &lt;value&gt; names vertex &lt;value&gt;, and the mesh has vertices 0..&lt;value&gt;”<br>“triangle count &lt;value&gt; is not a multiple of 3”<br>Also: “ → ” | Repair the triangles/hull and vertex order as the full message directs; split disconnected pieces into separate meshes with rigc split. |
7029
+
7030
+
7031
+ #### 5.1.6 Mesh generators, depth and soft regions
7032
+
7033
+ | Code | Fixed message text and alternatives | What to change |
7034
+ | --- | --- | --- |
7035
+ | <a id="CE_COMPILE_INTERNAL_GENERATED_MESH_OUTLINE_INVALID"></a>`CE_COMPILE_INTERNAL_GENERATED_MESH_OUTLINE_INVALID` | “&lt;value&gt;: internal: the &lt;value&gt; generator built an inconsistent mesh — &lt;value&gt;”<br>“hull vertices must come first; vertex &lt;value&gt; is on the boundary and vertex &lt;value&gt; is not. The triangles' outline runs &lt;value&gt;: list those &lt;value&gt; vertices first, in that order, then the &lt;value&gt; interior vertices”<br>“hull vertices must trace the outline in order; the triangles' outline runs &lt;value&gt;, so vertex &lt;value&gt; has to follow vertex &lt;value&gt; in the list, and vertex &lt;value&gt; does. Renumber the vertices along that walk”<br>“it declares hull &lt;value&gt; and its triangles outline &lt;value&gt; vertices”<br>“the triangles do not tile the outline: &lt;value&gt; vertices with a &lt;value&gt;-vertex outline tile as &lt;value&gt; triangles and there are &lt;value&gt; — Spine's binary reader derives the triangle count from exactly that, so a mesh that breaks it cannot be read back from a .skel”<br>“the triangles have no outline: every edge is shared by two triangles”<br>“the triangles' outline is not one closed loop: the walk from vertex &lt;value&gt; closes after &lt;value&gt; of &lt;value&gt; boundary vertices”<br>“the triangles' outline is not one closed loop: vertex &lt;value&gt; has &lt;value&gt; boundary edges”<br>“triangle &lt;value&gt; (&lt;value&gt;) repeats a vertex, so it has no area”<br>“triangle &lt;value&gt; names vertex &lt;value&gt;, and the mesh has vertices 0..&lt;value&gt;”<br>“triangle count &lt;value&gt; is not a multiple of 3”<br>Also: “ → ” | Report this generator defect with its kind and underlying outline refusal; generated topology must already be consistent. |
7036
+ | <a id="CE_COMPILE_MESH_AUTHORED_AND_GENERATED"></a>`CE_COMPILE_MESH_AUTHORED_AND_GENERATED` | “&lt;value&gt;: a mesh is either authored geometry or a generator, never both” | Use authored mesh geometry or a generator, rather than both. |
7037
+ | <a id="CE_COMPILE_MESH_GEOMETRY_SOURCES_CONFLICT"></a>`CE_COMPILE_MESH_GEOMETRY_SOURCES_CONFLICT` | “&lt;value&gt;: a mesh gives geometry as "vertices" or as "weights", never both — "weights" is the by-name form of the same data” | Supply vertices or by-name weights, rather than both. |
7038
+ | <a id="CE_COMPILE_MESH_GEOMETRY_MISSING"></a>`CE_COMPILE_MESH_GEOMETRY_MISSING` | “&lt;value&gt;: an authored mesh needs uvs, triangles and vertices or weights (or a "generator")” | Supply uvs/triangles and vertices or weights, or a generator. |
7039
+ | <a id="CE_COMPILE_MESH_WEIGHT_UV_COUNT"></a>`CE_COMPILE_MESH_WEIGHT_UV_COUNT` | “&lt;value&gt;: weights cover &lt;value&gt; vertices but there are &lt;value&gt; uv pairs” | Supply one weights entry per UV pair. |
7040
+ | <a id="CE_COMPILE_MESH_WEIGHTED_RUN_IMPLICIT"></a>`CE_COMPILE_MESH_WEIGHTED_RUN_IMPLICIT` | “&lt;value&gt;: this mesh's "vertices" is a weighted run, whose bone INDEXES point into the emitted bone array — a list the spec never writes, so inserting a bone rebinds every vertex in silence. Give the bindings by name as "weights": [[{ "bone": …, "x": …, "y": …, "weight": … }, …], …], or say "boneIndexing": "raw" on this attachment to keep the index form deliberately.” | Use by-name weights or explicitly request raw bone indexing for the weighted vertices run. |
7041
+ | <a id="CE_COMPILE_MESH_SIZE_MISSING"></a>`CE_COMPILE_MESH_SIZE_MISSING` | “&lt;value&gt;: a mesh needs width and height — give them, or give an "image" and rigc will measure the PNG” | State width/height or supply image for PNG measurement. |
7042
+ | <a id="CE_COMPILE_LINKED_MESH_GEOMETRY_IGNORED"></a>`CE_COMPILE_LINKED_MESH_GEOMETRY_IGNORED` | “&lt;value&gt;: a linked mesh states &lt;value&gt;, and a linked mesh has no geometry of its own — it draws the geometry of the attachment "source" names. The parser returns from the `source` branch before `readVertices` (`SkeletonJson.ts:582-586`), so these keys are read by nothing at all: a link declaring 5 uvs beside a 4-vertex source loads the SOURCE's 4 vertices and says nothing. Remove [it / them], or remove "source" and author this as a mesh of its own.”<br>Here the values named in the message include: “hull”, “edges”, “weights”, “generator”, “triangles”, “boneIndexing”. | Remove geometry keys from the link or remove source and author an ordinary mesh. |
7043
+ | <a id="CE_COMPILE_LINKED_MESH_SOURCE_MISSING"></a>`CE_COMPILE_LINKED_MESH_SOURCE_MISSING` | “&lt;value&gt;: a linked mesh needs "source" — the PLACEHOLDER of the mesh whose geometry it draws (the key that attachment is filed under in its skin, not its "name"), and this one states &lt;value&gt;. "source" is what MAKES a mesh linked: `getValue(map, "source", null)` is falsy-tested (`SkeletonJson.ts:582`), so an absent or empty one is read as an ordinary mesh, whose `uvs` this attachment does not have — the parser dereferences `map.uvs.length` and throws.” | Name the source mesh's placeholder in source. |
7044
+ | <a id="CE_COMPILE_LINKED_MESH_SLOT_UNKNOWN"></a>`CE_COMPILE_LINKED_MESH_SLOT_UNKNOWN` | “&lt;value&gt;: "slot" is &lt;value&gt;, which the rig does not declare as a slot. It names where the source lives and is resolved through `skeletonData.findSlot` (`SkeletonJson.ts:575`), which throws `Source mesh slot not found` on a miss. The rig's slots are &lt;value&gt;. Leave it out and the source is looked for in this attachment's own slot, which is the parser's default.” | Name the source slot declared by the rig, or omit slot for the link's own slot. |
7045
+ | <a id="CE_COMPILE_LINKED_MESH_SIZE_MISSING"></a>`CE_COMPILE_LINKED_MESH_SIZE_MISSING` | “&lt;value&gt;: a linked mesh needs width and height — give them, or give an "image" and rigc will measure the PNG” | State width/height or supply image for PNG measurement. |
7046
+ | <a id="CE_COMPILE_LINKED_MESH_DEFAULT_SKIN_MISSING"></a>`CE_COMPILE_LINKED_MESH_DEFAULT_SKIN_MISSING` | “&lt;value&gt;: no "skin" is stated, so the parser looks for the source "&lt;value&gt;" in the default skin — and this rig declares no default skin. The rig's skins are &lt;value&gt;. State the skin the source is filed under. Left to the round trip this is a `TypeError` off the null `SkeletonData.defaultSkin`, which names neither this attachment nor where it was looking.” | State the skin holding the source because this rig has no default skin. |
7047
+ | <a id="CE_COMPILE_LINKED_MESH_SKIN_UNKNOWN"></a>`CE_COMPILE_LINKED_MESH_SKIN_UNKNOWN` | “&lt;value&gt;: "skin" is &lt;value&gt;, and the rig declares no such skin. The rig's skins are &lt;value&gt;. Left to the round trip this is the runtime's `Skin not found`, which names neither this attachment nor where it was looking.” | Name the skin holding the source mesh. |
7048
+ | <a id="CE_COMPILE_LINKED_MESH_SOURCE_UNKNOWN"></a>`CE_COMPILE_LINKED_MESH_SOURCE_UNKNOWN` | “&lt;value&gt;: "source" is &lt;value&gt;, and skin &lt;value&gt;[ / (the default skin, because no "skin" was stated — never the skin this attachment is written in)] slot &lt;value&gt;[ / (this attachment's own slot, because no "slot" was stated)] holds [no attachment at all / &lt;value&gt;: &lt;value&gt;]. "source" is the PLACEHOLDER the source is filed under — `skin.getAttachment(slotIndex, source)` (`SkeletonJson.ts:433`), whose table is keyed by the JSON key, not by the attachment's `name`. Left to the round trip this is the runtime's `Source mesh not found`.” | Name the source mesh's placeholder in the correct skin and slot. |
7049
+ | <a id="CE_COMPILE_LINKED_MESH_SOURCE_IS_LINK"></a>`CE_COMPILE_LINKED_MESH_SOURCE_IS_LINK` | “&lt;value&gt;: "source" is &lt;value&gt;, which is itself a linked mesh, and a chain of them is refused. Measured through spine-core: the runtime resolves links in the order they were read, so a link whose source is a link loads the source's geometry when the source comes first in the file and loads NOTHING — `worldVerticesLength` 0, 0 triangles, a 0x0 size — when the two are swapped, in silence either way. Point "source" at the mesh itself.” | Point source directly at the ordinary mesh rather than another linked mesh. |
7050
+ | <a id="CE_COMPILE_LINKED_MESH_SOURCE_NOT_MESH"></a>`CE_COMPILE_LINKED_MESH_SOURCE_NOT_MESH` | “&lt;value&gt;: "source" is &lt;value&gt;, which is a &lt;value&gt; attachment and not a mesh. A linked mesh takes another MESH's `uvs`, `triangles`, `vertices`, `hull` and `edges` (`MeshAttachment.setSourceMesh`); the runtime casts whatever it finds and reads those fields off it, which on any other type is `undefined` and no error.” | Point source at a mesh attachment. |
7051
+ | <a id="CE_COMPILE_MESH_BONE_UNKNOWN"></a>`CE_COMPILE_MESH_BONE_UNKNOWN` | “&lt;value&gt;: mesh bone "&lt;value&gt;" is not in the rig's bone list” | Use mesh bone names declared in the rig. |
7052
+ | <a id="CE_COMPILE_MESH_BONE_TRANSFORM_MISSING"></a>`CE_COMPILE_MESH_BONE_TRANSFORM_MISSING` | “&lt;value&gt;: no setup transform for mesh bone "&lt;value&gt;"” | Correct the mesh bone/setup hierarchy; report a missing compiled transform for a declared bone. |
7053
+ | <a id="CE_COMPILE_RING_RIBBON_GENERATOR_INVALID"></a>`CE_COMPILE_RING_RIBBON_GENERATOR_INVALID` | “&lt;value&gt;: &lt;value&gt;”<br>“a polygon vertex sits exactly on the aperture centre”<br>“a ring mesh needs at least one control bone”<br>“aperture centre (&lt;value&gt;,&lt;value&gt;) is outside the &lt;value&gt;x&lt;value&gt; part window”<br>“bad part size &lt;value&gt;x&lt;value&gt;”<br>“bias ramp must increase, got [&lt;value&gt;, &lt;value&gt;]”<br>“control bone "&lt;value&gt;" sits on the aperture centre, so it has no radial direction”<br>“hull is not star-shaped about the aperture centre; the inner ring would fold”<br>“hull needs at least 6 points, got &lt;value&gt;”<br>“hull point (&lt;value&gt;,&lt;value&gt;) is outside the &lt;value&gt;x&lt;value&gt; part window”<br>“inner must be in (0,1), got &lt;value&gt;”<br>“ray to the window edge did not converge”<br>“ribbon needs at least 3 rows, got &lt;value&gt;”<br>“ribbon needs at least one chain bone, got &lt;value&gt;”<br>“two control bones share the angle &lt;value&gt; degrees about the aperture centre”<br>Also: “&lt;value&gt;: mesh bone "&lt;value&gt;" is not in the rig's bone list”<br>“&lt;value&gt;: no setup transform for mesh bone "&lt;value&gt;"” | Correct the ring/ribbon dimensions, hull, centre, inner, bias or controls as the full generator message states. |
7054
+ | <a id="CE_COMPILE_DEPTH_IMAGE_MISSING"></a>`CE_COMPILE_DEPTH_IMAGE_MISSING` | “&lt;value&gt;: the depth block has no "image"; it is the sheet to sample, relative to the rig's images directory” | State the depth image relative to the rig images directory. |
7055
+ | <a id="CE_COMPILE_DEPTH_NEAR_INVALID"></a>`CE_COMPILE_DEPTH_NEAR_INVALID` | “&lt;value&gt;: the depth block says "near": &lt;value&gt;; it is "white" or "black". Both conventions are in use, and a sheet read with the wrong one turns the part inside out with every gate green.” | State near as white or black to declare the sheet convention. |
7056
+ | <a id="CE_COMPILE_DEPTH_TONE_SCALE_INVALID"></a>`CE_COMPILE_DEPTH_TONE_SCALE_INVALID` | “&lt;value&gt;: "zScale" is &lt;value&gt;; it is a finite number of world units”<br>“&lt;value&gt;: "zScale" is &lt;value&gt;; it is how many units the map's full range spans, so a positive number. To put the near end at the back, say "near": "black" — a negative scale states the same thing twice and the two can then disagree.”<br>“&lt;value&gt;: depth tone "&lt;value&gt;" is &lt;value&gt;; it is a finite number”<br>“&lt;value&gt;: depth tone "contrast" is &lt;value&gt;; a contrast at or below 0 collapses the range onto the midpoint (or turns it inside out), so the map would describe a flat part. It is a positive number, and 1 leaves the range alone.”<br>“&lt;value&gt;: depth tone "gamma" is &lt;value&gt;; a gamma at or below 0 maps every level to the same nearness, so the map would describe a flat part. It is a positive number, and 1 is the straight line.”<br>Here the values named in the message include: “bias”. | Use finite depth tone values, positive gamma/contrast and a positive finite zScale. |
7057
+ | <a id="CE_COMPILE_DEPTH_COVERAGE_INCOMPLETE"></a>`CE_COMPILE_DEPTH_COVERAGE_INCOMPLETE` | “&lt;value&gt;: the depth map "&lt;value&gt;" does not cover &lt;value&gt; of the mesh's &lt;value&gt; vertices — the first is vertex &lt;value&gt; at (&lt;value&gt;, &lt;value&gt;)[ / in the page's texels, pixel (&lt;value&gt;, &lt;value&gt;) of the drawing-sized sheet]. &lt;value&gt; Sampling anyway would give those vertices the sheet's background depth and fold them away from the turn.”<br>“[A contour mesh puts every vertex ON the silhouette and pushes it out by the margin, so a sheet cut to the art stops short of every one of them. Dilate the sheet past the mesh margin, or lower the margin. / A grid spans the whole part window, corners included, while a sheet is usually cut to the art — so the lattice reaches past it wherever the art does not fill the window. Dilate the sheet to the window, or state "us"/"vs" that keep the lattice inside the art.]” | Supply a depth sheet covering every mesh vertex in the part's drawing-sized pixel grid. |
7058
+ | <a id="CE_COMPILE_MESH_BONE_SETUP_TRANSFORM_MISSING"></a>`CE_COMPILE_MESH_BONE_SETUP_TRANSFORM_MISSING` | “&lt;value&gt;: bone "&lt;value&gt;" has no setup transform” | Correct the bone/setup hierarchy; report a missing compiled transform for a declared bone. |
7059
+ | <a id="CE_COMPILE_MESH_BONE_NOT_DECLARED"></a>`CE_COMPILE_MESH_BONE_NOT_DECLARED` | “&lt;value&gt;: bone "&lt;value&gt;" is not in the rig's bone list” | Use a bone name declared in the rig. |
7060
+ | <a id="CE_COMPILE_GREY_SHEET_IMAGE_MISSING"></a>`CE_COMPILE_GREY_SHEET_IMAGE_MISSING` | “&lt;value&gt;: the "&lt;value&gt;" block has no image to read” | State the image in the named depth/soft block. |
7061
+ | <a id="CE_COMPILE_GREY_SHEET_IMAGE_NOT_FOUND"></a>`CE_COMPILE_GREY_SHEET_IMAGE_NOT_FOUND` | “&lt;value&gt;: the &lt;value&gt; "&lt;value&gt;" is not at &lt;value&gt;”<br>Also: “{depth map / soft mask}” | Supply the named sheet at the images path or correct its image name. |
7062
+ | <a id="CE_COMPILE_GREY_SHEET_SIZE_MISMATCH"></a>`CE_COMPILE_GREY_SHEET_SIZE_MISMATCH` | “[&lt;value&gt;: the &lt;value&gt; "&lt;value&gt;" is &lt;value&gt;x&lt;value&gt; and the part is &lt;value&gt;x&lt;value&gt;. It is sampled in the part's own pixel grid, so the two are the same size — resample the sheet, or point at the one that was made for this part. / &lt;value&gt;: the &lt;value&gt; "&lt;value&gt;" is &lt;value&gt;x&lt;value&gt; and the part is a &lt;value&gt;x&lt;value&gt; drawing — &lt;value&gt;x&lt;value&gt; texels on a page that declares scale: &lt;value&gt;, which makes a texel &lt;value&gt;px of the drawing. It is sampled in the part's own pixel grid, which is the drawing's, at each vertex's texel position over that scale — so the sheet is &lt;value&gt;x&lt;value&gt;, the size of the loose art, whatever the page holds. Resample the sheet, or point at the one that was made for this part.]”<br>Also: “{depth map / soft mask}” | Resample the sheet to the part's drawing-sized grid, accounting for imported atlas scale. |
7063
+ | <a id="CE_COMPILE_GREY_SHEET_NOT_GREYSCALE"></a>`CE_COMPILE_GREY_SHEET_NOT_GREYSCALE` | “&lt;value&gt;: the &lt;value&gt; "&lt;value&gt;" is not greyscale — pixel (&lt;value&gt;, &lt;value&gt;) is rgb(&lt;value&gt;, &lt;value&gt;, &lt;value&gt;). It is one channel; reading red out of a colour file would use whatever that channel happened to hold.”<br>Also: “{depth map / soft mask}” | Supply a single-tone greyscale sheet with equal red/green/blue channels. |
7064
+ | <a id="CE_COMPILE_SOFT_BONE_MISSING"></a>`CE_COMPILE_SOFT_BONE_MISSING` | “&lt;value&gt;: the "soft" block has no "bone"; it is the bone the soft region is carried by” | Name the independent bone carrying the soft region. |
7065
+ | <a id="CE_COMPILE_SOFT_BONE_UNKNOWN"></a>`CE_COMPILE_SOFT_BONE_UNKNOWN` | “&lt;value&gt;: "soft" names bone "&lt;value&gt;", which this rig does not declare. rigc binds a region to a bone that already exists rather than creating one — a bone a physics constraint has to target is part of the skeleton, not a side effect of a mesh.” | Declare the soft region's bone in the rig. |
7066
+ | <a id="CE_COMPILE_SOFT_BONE_IS_ANCHOR"></a>`CE_COMPILE_SOFT_BONE_IS_ANCHOR` | “&lt;value&gt;: "soft" names "&lt;value&gt;", which is this slot's own bone. Carrying the region with the bone the rest of the mesh is already pinned to moves nothing — a soft region needs a bone that can move independently, which is what a physics constraint is put on.” | Use a bone that moves independently of the slot's anchor bone. |
7067
+ | <a id="CE_COMPILE_SOFT_MASK_INERT"></a>`CE_COMPILE_SOFT_MASK_INERT` | “&lt;value&gt;: the soft mask "&lt;value&gt;" carries no vertex of this mesh — every one of its &lt;value&gt; vertices samples black. A region that moves nothing is a physics constraint with nothing on the end of it; check that the mask is painted where the mesh actually is, and that it is white where the art is soft.” | Paint the soft mask white where the mesh has soft vertices. |
7068
+ | <a id="CE_COMPILE_GRID_IMAGE_MISSING"></a>`CE_COMPILE_GRID_IMAGE_MISSING` | “&lt;value&gt;: a "grid" generator lays its lattice over the part's own window, so the attachment needs an "image" — there is nothing else here that says how big that window is” | Supply image so the grid has a measured part window. |
7069
+ | <a id="CE_COMPILE_GRID_POSITIONS_AND_COUNT"></a>`CE_COMPILE_GRID_POSITIONS_AND_COUNT` | “&lt;value&gt;: the "grid" generator states both positions ("us"/"vs") and a count ("cols"/"rows"). They are two answers to where the columns go, and a spec carrying both leaves a reader unable to say which one built the mesh. Drop one — positions are the more precise of the two.” | Choose explicit us/vs positions or cols/rows counts. |
7070
+ | <a id="CE_COMPILE_GRID_POSITION_AND_COUNT_MISSING"></a>`CE_COMPILE_GRID_POSITION_AND_COUNT_MISSING` | “&lt;value&gt;: the "grid" generator says neither where its columns go ("us"/"vs", fractions of the window) nor how many there are ("cols"/"rows"). A lattice is not a default.” | State us/vs positions or cols/rows counts. |
7071
+ | <a id="CE_COMPILE_GRID_COUNT_INVALID"></a>`CE_COMPILE_GRID_COUNT_INVALID` | “&lt;value&gt;: "&lt;value&gt;" is &lt;value&gt;; it is a whole number of at least 2” | State cols/rows as whole numbers of at least two. |
7072
+ | <a id="CE_COMPILE_GRID_AXIS_MISSING"></a>`CE_COMPILE_GRID_AXIS_MISSING` | “&lt;value&gt;: the "grid" generator states ["vs" / "us"] and not ["us" / "vs"]; a lattice needs both axes” | State both us and vs axes. |
7073
+ | <a id="CE_COMPILE_GRID_GENERATOR_INVALID"></a>`CE_COMPILE_GRID_GENERATOR_INVALID` | “"&lt;value&gt;" has [&lt;value&gt; / &lt;value&gt;] positions; a grid needs at least 2 on each axis”<br>“"&lt;value&gt;" is not ascending: [&lt;value&gt;]=&lt;value&gt; and [&lt;value&gt;]=&lt;value&gt;”<br>“"&lt;value&gt;"[&lt;value&gt;] is &lt;value&gt;; positions are finite numbers”<br>“"&lt;value&gt;"[&lt;value&gt;] is &lt;value&gt;; positions are fractions of the part window, 0..1”<br>“&lt;value&gt;: &lt;value&gt;”<br>“the part window is &lt;value&gt;x&lt;value&gt;; a grid needs a positive size” | Correct the grid's finite ascending 0..1 axis positions and positive part size as the full message states. |
7074
+ | <a id="CE_COMPILE_GENERATED_IMAGE_WIDTH_MISMATCH"></a>`CE_COMPILE_GENERATED_IMAGE_WIDTH_MISMATCH` | “&lt;value&gt;: the spec says width &lt;value&gt; and "&lt;value&gt;" measures &lt;value&gt;” | Make attachment width agree with the measured image width. |
7075
+ | <a id="CE_COMPILE_GENERATED_IMAGE_HEIGHT_MISMATCH"></a>`CE_COMPILE_GENERATED_IMAGE_HEIGHT_MISMATCH` | “&lt;value&gt;: the spec says height &lt;value&gt; and "&lt;value&gt;" measures &lt;value&gt;” | Make attachment height agree with the measured image height. |
7076
+ | <a id="CE_COMPILE_SLOT_BONE_NOT_DECLARED"></a>`CE_COMPILE_SLOT_BONE_NOT_DECLARED` | “&lt;value&gt;: slot bone "&lt;value&gt;" is not in the rig's bone list” | Use a slot bone declared in the rig. |
7077
+ | <a id="CE_COMPILE_SEGMENTS_FALLOFF_RADIUS_INVALID"></a>`CE_COMPILE_SEGMENTS_FALLOFF_RADIUS_INVALID` | “&lt;value&gt;: "falloff.radius" is &lt;value&gt;; it is added to every distance before the power is taken, a positive number of the part's pixels — at 0 a vertex on a segment would carry an infinite pull” | State a positive finite falloff radius in part pixels. |
7078
+ | <a id="CE_COMPILE_SEGMENTS_FALLOFF_POWER_INVALID"></a>`CE_COMPILE_SEGMENTS_FALLOFF_POWER_INVALID` | “&lt;value&gt;: "falloff.power" is &lt;value&gt;; it is the exponent a pull falls off with distance by, a positive number — at 0 or below the far segment pulls as hard as the near one, or harder” | State a positive finite falloff power. |
7079
+ | <a id="CE_COMPILE_SEGMENTS_FALLOFF_MAX_BONES_INVALID"></a>`CE_COMPILE_SEGMENTS_FALLOFF_MAX_BONES_INVALID` | “&lt;value&gt;: "falloff.maxBones" is &lt;value&gt;; it is how many bones may pull one vertex, a whole number of at least 1” | State falloff.maxBones as a whole number of at least one. |
7080
+ | <a id="CE_COMPILE_SEGMENTS_FALLOFF_MIN_WEIGHT_INVALID"></a>`CE_COMPILE_SEGMENTS_FALLOFF_MIN_WEIGHT_INVALID` | “&lt;value&gt;: "falloff.minWeight" is &lt;value&gt;; it is the share under which a bone's pull is dropped, so it lies in &lt;value&gt;..1 with 1 excluded — at 1 or above every share is dropped, and under &lt;value&gt;, one step of the 6-decimal grid weights are written on, a kept binding could be written as 0” | State falloff.minWeight on or above the weight grid step and below one. |
7081
+ | <a id="CE_COMPILE_SEGMENTS_WEIGHT_MODE_CONFLICT"></a>`CE_COMPILE_SEGMENTS_WEIGHT_MODE_CONFLICT` | “&lt;value&gt;: the "segments" generator states both "falloff" and "influence". Both turn a distance into a share — "falloff" as 1 / (d + radius)^power over every segment, "influence" as a pull that reaches zero at its "radius" — and a mesh is weighted by one of them: remove the other” | Use falloff or influence, rather than both. |
7082
+ | <a id="CE_COMPILE_SEGMENTS_INFLUENCE_INVALID"></a>`CE_COMPILE_SEGMENTS_INFLUENCE_INVALID` | “&lt;value&gt;: "influence" is &lt;value&gt;; it is { "radius", "across", "max", "shape" }, every one required” | State influence with radius/across/max/shape, every field required. |
7083
+ | <a id="CE_COMPILE_SEGMENTS_INFLUENCE_RADIUS_INVALID"></a>`CE_COMPILE_SEGMENTS_INFLUENCE_RADIUS_INVALID` | “&lt;value&gt;: "influence.radius" is &lt;value&gt;; it is how far a link reaches, in the part's pixels, a positive number with no default — a length on this art: a link whose segment is that far from a vertex or farther never pulls it”<br>Here the values named in the message include: “absent”. | State positive finite influence.radius in part pixels. |
7084
+
7085
+
7086
+ #### 5.1.7 Mesh generators, depth and soft regions (2)
7087
+
7088
+ | Code | Fixed message text and alternatives | What to change |
7089
+ | --- | --- | --- |
7090
+ | <a id="CE_COMPILE_SEGMENTS_INFLUENCE_ACROSS_INVALID"></a>`CE_COMPILE_SEGMENTS_INFLUENCE_ACROSS_INVALID` | “&lt;value&gt;: "influence.across" is &lt;value&gt;; it is true (every link within "radius" pulls, across the entries of "bones") or false (only the links of the entry nearest the vertex), with no default — whether a chain may pull its neighbour's cloth is the decision this field is”<br>Here the values named in the message include: “absent”. | State influence.across as true or false. |
7091
+ | <a id="CE_COMPILE_SEGMENTS_INFLUENCE_MAX_INVALID"></a>`CE_COMPILE_SEGMENTS_INFLUENCE_MAX_INVALID` | “&lt;value&gt;: "influence.max" is &lt;value&gt;; it is how many links may pull one vertex, the strongest kept, a whole number of at least 1 with no default”<br>Here the values named in the message include: “absent”. | State influence.max as a whole number of at least one. |
7092
+ | <a id="CE_COMPILE_SEGMENTS_INFLUENCE_SHAPE_INVALID"></a>`CE_COMPILE_SEGMENTS_INFLUENCE_SHAPE_INVALID` | “&lt;value&gt;: "influence.shape" is &lt;value&gt;; one of &lt;value&gt; — how a pull falls from 1 on a link to 0 at "radius", with no default: "linear" is 1 - d/radius, "smooth" arrives at both ends with zero slope”<br>Here the values named in the message include: “absent”. | State influence.shape as linear or smooth. |
7093
+ | <a id="CE_COMPILE_SEGMENTS_IMAGE_MISSING"></a>`CE_COMPILE_SEGMENTS_IMAGE_MISSING` | “&lt;value&gt;: a "segments" generator lays its lattice over the part's own alpha, so the attachment needs an "image" — there is nothing else here that says which pixels are art” | Supply image so the lattice measures the part's alpha. |
7094
+ | <a id="CE_COMPILE_SEGMENTS_ATLAS_GRID_UNSUPPORTED"></a>`CE_COMPILE_SEGMENTS_ATLAS_GRID_UNSUPPORTED` | “&lt;value&gt;. &lt;value&gt;”<br>“&lt;value&gt;. &lt;value&gt; &lt;value&gt;”<br>“&lt;value&gt;: a "segments" generator lays its lattice over the part's own alpha, and "&lt;value&gt;" is lifted off a packed page at the coordinates the atlas states, which on this file are not where its texels are — so there is no art here to cover, only another part of the page. &lt;value&gt;”<br>“A runtime does not read the file's own size anywhere in the region mapping — `TextureAtlas` computes every region's UVs as a fraction of the DECLARED size (`region.u = region.x / page.width`, spine-core `dist/TextureAtlas.js:162-171`) — so a page whose PNG is the declared page RESCALED draws the same picture at the file's resolution, and one whose PNG is anything else draws whatever sits at those fractions. What a declared size that disagrees with the file breaks is every reader that addresses the page in TEXELS: this validator's own `A19` alpha scan, the region lift rigc's mesh generators trace, and a canvas renderer that cuts each part out of the page by source rectangle.”<br>“[&lt;value&gt; / &lt;value&gt; — &lt;value&gt; of the declared width and &lt;value&gt; of the declared height]”<br>“[The `scale:` header states one ratio for both axes, so a page whose axes differ cannot be declared honestly at all: re-export the page at &lt;value&gt;x&lt;value&gt;, or repack it. / [The format states coarser texels with the `scale:` header, but this page cannot be re-declared that way: &lt;value&gt;. Re-export the page at &lt;value&gt;x&lt;value&gt;, or repack it. / The format states coarser texels with the `scale:` header and rigc builds that: declare `size: &lt;value&gt;, &lt;value&gt;` with `scale: &lt;value&gt;` and multiply every `bounds`/`offsets` on this page by &lt;value&gt;, and every part keeps the size it has now.]]”<br>“page "&lt;value&gt;" declares &lt;value&gt;x&lt;value&gt; and its PNG is &lt;value&gt;x&lt;value&gt;”<br>“region &lt;value&gt;'s `&lt;value&gt;` of &lt;value&gt; becomes &lt;value&gt; on the file's own grid, which is not a whole texel” | Use correctly addressed atlas pixels or the loose part image for the alpha lattice. |
7095
+ | <a id="CE_COMPILE_SEGMENTS_ATLAS_SCALE_UNSUPPORTED"></a>`CE_COMPILE_SEGMENTS_ATLAS_SCALE_UNSUPPORTED` | “&lt;value&gt;: a "segments" generator measures its "cell" and its falloff "radius" in the part's pixels, and "&lt;value&gt;" sits on a page that declares scale: &lt;value&gt;, where a pixel of the drawing is not a texel of the page. This generator does not convert between the two; build it from the loose part, or from a pack at scale 1” | Build segments from the loose part or an atlas at scale one. |
7096
+ | <a id="CE_COMPILE_SEGMENTS_WEIGHT_MODE_MISSING"></a>`CE_COMPILE_SEGMENTS_WEIGHT_MODE_MISSING` | “&lt;value&gt;: the "segments" generator states no "falloff" block. Its "radius" — added to every distance, in the part's pixels — has no default, because it is a length on this art: "falloff": { "radius": &lt;pixels&gt; } is the least it takes (or an "influence" block, whose pull reaches zero at its own "radius")” | State falloff.radius or a complete influence block. |
7097
+ | <a id="CE_COMPILE_SEGMENTS_LATTICE_INVALID"></a>`CE_COMPILE_SEGMENTS_LATTICE_INVALID` | “"cell" is &lt;value&gt;; it is the lattice's square, a whole number of pixels of at least 1”<br>“&lt;value&gt;: &lt;value&gt;”<br>“no pixel of the &lt;value&gt;x&lt;value&gt; part reaches alpha &lt;value&gt;, so a lattice at cell &lt;value&gt; keeps no cell — there is no art to cover. Lower "alpha", or point at the image this mesh is meant to draw”<br>“the alpha threshold must be a whole number in 1..255, got &lt;value&gt;” | Use a whole positive cell size, a valid alpha threshold and art that keeps at least one lattice cell. |
7098
+ | <a id="CE_COMPILE_SEGMENTS_ANCHOR_INVALID"></a>`CE_COMPILE_SEGMENTS_ANCHOR_INVALID` | “&lt;value&gt;: "anchor" is &lt;value&gt;; it is where the slot bone sits in the part's pixels, y down, as [x, y] — two finite numbers” | State anchor as two finite part-pixel coordinates, y down. |
7099
+ | <a id="CE_COMPILE_SEGMENTS_BONES_EMPTY"></a>`CE_COMPILE_SEGMENTS_BONES_EMPTY` | “&lt;value&gt;: the "segments" generator names no bones. "bones" is the one decision this generator takes — which segments may pull the part — so it lists at least one: a bone name, a chain as a list of bone names, or { "bone", "from", "to" }” | Name at least one bone, chain or explicit bone segment. |
7100
+ | <a id="CE_COMPILE_SEGMENTS_BONE_UNKNOWN"></a>`CE_COMPILE_SEGMENTS_BONE_UNKNOWN` | “&lt;value&gt;: &lt;value&gt; names mesh bone &lt;value&gt;, which is not in the rig's bone list”<br>Also: “"bones"[&lt;value&gt;]”<br>“&lt;value&gt;.bone” | Name mesh bones declared by the rig. |
7101
+ | <a id="CE_COMPILE_SEGMENTS_BONE_LENGTH_MISSING"></a>`CE_COMPILE_SEGMENTS_BONE_LENGTH_MISSING` | “&lt;value&gt;: &lt;value&gt; names bone "&lt;value&gt;", which has no "length"[ and is the last link of its chain / ], so it has an origin and no segment. Give the bone a "length" (its segment runs from its origin to that tip, along its setup rotation), [end the chain on a bone that has one, / name it inside a chain whose next link says where it ends, ]or state the segment outright as { "bone", "from", "to" }”<br>Also: “"bones"[&lt;value&gt;]” | Give the bone a length, a following chain link, or explicit from/to endpoints. |
7102
+ | <a id="CE_COMPILE_SEGMENTS_CHAIN_EMPTY"></a>`CE_COMPILE_SEGMENTS_CHAIN_EMPTY` | “&lt;value&gt;: &lt;value&gt; is an empty chain; a chain lists its bones root first, at least one”<br>Also: “"bones"[&lt;value&gt;]” | List at least one chain bone root first. |
7103
+ | <a id="CE_COMPILE_SEGMENTS_CHAIN_ORDER_INVALID"></a>`CE_COMPILE_SEGMENTS_CHAIN_ORDER_INVALID` | “&lt;value&gt;: &lt;value&gt; chains "&lt;value&gt;" to "&lt;value&gt;", and "&lt;value&gt;" is not under "&lt;value&gt;" in the bone tree — a chain runs down the skeleton, each link a descendant of the one before it. List the chain root first, or name the two bones as separate entries”<br>Also: “"bones"[&lt;value&gt;]” | List chain bones root first with each next link a descendant, or use separate entries. |
7104
+ | <a id="CE_COMPILE_SEGMENTS_CHAIN_ZERO_LENGTH"></a>`CE_COMPILE_SEGMENTS_CHAIN_ZERO_LENGTH` | “&lt;value&gt;: &lt;value&gt; chains "&lt;value&gt;" to "&lt;value&gt;", and the two bones share their setup origin (&lt;value&gt;, &lt;value&gt;), so the link has no length and no direction to weight along. Give "&lt;value&gt;" its own position, or name "&lt;value&gt;" alone with a "length"”<br>Also: “"bones"[&lt;value&gt;]” | Give the next bone its own position or use a lone bone with length. |
7105
+ | <a id="CE_COMPILE_SEGMENTS_ENDPOINT_INVALID"></a>`CE_COMPILE_SEGMENTS_ENDPOINT_INVALID` | “&lt;value&gt;: &lt;value&gt; states a segment whose ["from" / "to"] is &lt;value&gt;; both ends are [x, y] in the part's pixels, y down”<br>Also: “"bones"[&lt;value&gt;]” | State both segment endpoints as finite x/y pairs in part pixels, y down. |
7106
+ | <a id="CE_COMPILE_SEGMENTS_ENTRY_INVALID"></a>`CE_COMPILE_SEGMENTS_ENTRY_INVALID` | “&lt;value&gt;: &lt;value&gt; is &lt;value&gt;; an entry is a bone name, a chain as a list of bone names, or { "bone", "from", "to" }”<br>Also: “"bones"[&lt;value&gt;]” | Use a bone name, a root-first bone chain or an explicit bone/from/to segment. |
7107
+ | <a id="CE_COMPILE_SEGMENTS_VERTEX_UNREACHED"></a>`CE_COMPILE_SEGMENTS_VERTEX_UNREACHED` | “&lt;value&gt;: vertex &lt;value&gt;, at (&lt;value&gt;, &lt;value&gt;) in the part's pixels, is reached by no link — the nearest is "&lt;value&gt;" at &lt;value&gt;, and "influence.radius" is &lt;value&gt;[ / (with "across": false, the nearest entry's links only)]. A vertex needs a link, and rigc will not hand it one the reach does not: raise "radius" over that distance, or name a segment nearer this part of the art” | Raise influence.radius beyond the nearest link distance or name a nearer segment. |
7108
+ | <a id="CE_COMPILE_SEGMENTS_VERTEX_WEIGHTS_DROPPED"></a>`CE_COMPILE_SEGMENTS_VERTEX_WEIGHTS_DROPPED` | “&lt;value&gt;: vertex &lt;value&gt;, at (&lt;value&gt;, &lt;value&gt;) in the part's pixels, keeps no bone — the &lt;value&gt; strongest pull(s) share it as &lt;value&gt;, and every one is under "minWeight" &lt;value&gt;. A vertex needs a bone, and rigc will not pick one the falloff dropped: lower "minWeight" to &lt;value&gt; or under (1 / "maxBones", which the strongest share can never fall below), or name a segment nearer this part of the art” | Lower minWeight to at most 1/maxBones or name a segment nearer the art. |
7109
+ | <a id="CE_COMPILE_CONTOUR_IMAGE_MISSING"></a>`CE_COMPILE_CONTOUR_IMAGE_MISSING` | “&lt;value&gt;: a "contour" generator traces the part's own alpha, so the attachment needs an "image" — there is nothing else here that says which pixels to measure” | Supply image so the contour measures the part's alpha. |
7110
+ | <a id="CE_COMPILE_CONTOUR_ATLAS_GRID_UNSUPPORTED"></a>`CE_COMPILE_CONTOUR_ATLAS_GRID_UNSUPPORTED` | “&lt;value&gt;. &lt;value&gt;”<br>“&lt;value&gt;. &lt;value&gt; &lt;value&gt;”<br>“&lt;value&gt;: a "contour" generator traces the part's own alpha, and "&lt;value&gt;" is lifted off a packed page at the coordinates the atlas states, which on this file are not where its texels are — so there is no silhouette here to trace, only another part of the page. &lt;value&gt;”<br>“A runtime does not read the file's own size anywhere in the region mapping — `TextureAtlas` computes every region's UVs as a fraction of the DECLARED size (`region.u = region.x / page.width`, spine-core `dist/TextureAtlas.js:162-171`) — so a page whose PNG is the declared page RESCALED draws the same picture at the file's resolution, and one whose PNG is anything else draws whatever sits at those fractions. What a declared size that disagrees with the file breaks is every reader that addresses the page in TEXELS: this validator's own `A19` alpha scan, the region lift rigc's mesh generators trace, and a canvas renderer that cuts each part out of the page by source rectangle.”<br>“[&lt;value&gt; / &lt;value&gt; — &lt;value&gt; of the declared width and &lt;value&gt; of the declared height]”<br>“[The `scale:` header states one ratio for both axes, so a page whose axes differ cannot be declared honestly at all: re-export the page at &lt;value&gt;x&lt;value&gt;, or repack it. / [The format states coarser texels with the `scale:` header, but this page cannot be re-declared that way: &lt;value&gt;. Re-export the page at &lt;value&gt;x&lt;value&gt;, or repack it. / The format states coarser texels with the `scale:` header and rigc builds that: declare `size: &lt;value&gt;, &lt;value&gt;` with `scale: &lt;value&gt;` and multiply every `bounds`/`offsets` on this page by &lt;value&gt;, and every part keeps the size it has now.]]”<br>“page "&lt;value&gt;" declares &lt;value&gt;x&lt;value&gt; and its PNG is &lt;value&gt;x&lt;value&gt;”<br>“region &lt;value&gt;'s `&lt;value&gt;` of &lt;value&gt; becomes &lt;value&gt; on the file's own grid, which is not a whole texel” | Use correctly addressed atlas pixels or the loose part image for the alpha contour. |
7111
+ | <a id="CE_COMPILE_CONTOUR_GENERATOR_INVALID"></a>`CE_COMPILE_CONTOUR_GENERATOR_INVALID` | “&lt;value&gt;: &lt;value&gt;”<br>“[ / (the drawing's pixels — applied as &lt;value&gt; texel(s) of this page, whose scale: &lt;value&gt; makes a texel &lt;value&gt;px of the drawing)]”<br>“[px / texels]”<br>“a polygon needs at least 3 vertices to triangulate, got &lt;value&gt;”<br>“bad part size &lt;value&gt;x&lt;value&gt;”<br>“ear clipping stalled with &lt;value&gt; of &lt;value&gt; vertices left: every remaining corner is reflex or covers another vertex, which a strictly simple polygon cannot be — the outline is degenerate”<br>“every pixel of the &lt;value&gt;x&lt;value&gt; part reaches alpha &lt;value&gt;, so its silhouette IS the part window and a contour mesh of it is a region attachment with extra vertices — give the art a transparent margin, raise the alpha threshold, or use a region”<br>“maxVertices must be a whole number of at least 3, got &lt;value&gt;”<br>“no pixel of the &lt;value&gt;x&lt;value&gt; part reaches alpha &lt;value&gt;; there is no silhouette to trace”<br>“the &lt;value&gt;x&lt;value&gt; silhouette simplified to &lt;value&gt; distinct vertices at tolerance &lt;value&gt;&lt;value&gt;; lower the tolerance”<br>“the alpha mask holds &lt;value&gt; bytes for a &lt;value&gt;x&lt;value&gt; part”<br>“the alpha silhouette pinches to a single point at pixel corner (&lt;value&gt;,&lt;value&gt;), where two parts of the art meet diagonally — one outline cannot pass through one point twice. Move the alpha threshold so the pinch opens (raise it) or closes (lower it), or author the geometry as weights”<br>“the alpha threshold must be a whole number in 1..255, got &lt;value&gt;”<br>“the alpha trace did not close; the mask is not a closed region”<br>“the alpha trace reached a dead end at corner (&lt;value&gt;,&lt;value&gt;); the mask is not a closed region”<br>“the art is &lt;value&gt; separate islands and one outline can only enclose the largest (&lt;value&gt; of &lt;value&gt; px, &lt;value&gt;%) — raise the alpha threshold if the strays are feathering, or give each island its own slot”<br>“the margin must be 0 or more pixels, got &lt;value&gt;”<br>“the mesh covers &lt;value&gt;% of the art (&lt;value&gt; of &lt;value&gt; &lt;value&gt;), under the &lt;value&gt;% a contour mesh guarantees — raise the margin (now &lt;value&gt;px) above the tolerance (&lt;value&gt;px), which is how far simplification is allowed to cut inward, or lower the tolerance&lt;value&gt;”<br>“the mesh reaches &lt;value&gt;px past the silhouette, past the &lt;value&gt;px that a margin of &lt;value&gt; and a tolerance of &lt;value&gt;&lt;value&gt; can produce — the outline is not the one this builder promises, which is a defect in the builder rather than in the art”<br>“the outline crosses itself: edge &lt;value&gt; meets edge &lt;value&gt; after a margin of &lt;value&gt;px&lt;value&gt; was pushed out of a silhouette narrower than that — lower the margin, or the art has a neck too thin to mesh”<br>“the polygon encloses no area, so it has no triangles”<br>“the silhouette simplified to &lt;value&gt; vertices at tolerance &lt;value&gt;&lt;value&gt;, past the &lt;value&gt; this mesh allows — raise the tolerance to spend fewer vertices, or raise maxVertices if the shape needs them”<br>“the simplification tolerance must be a positive number of pixels, got &lt;value&gt;” | Follow the named alpha, tolerance, margin or topology repair. If the message says the builder overshot its declared margin, report the compiler defect with the measured overshoot and minimal inputs; preserve the art. |
7112
+
7113
+
7114
+ #### 5.1.8 Constraints and rig invariants
7115
+
7116
+ | Code | Fixed message text and alternatives | What to change |
7117
+ | --- | --- | --- |
7118
+ | <a id="CE_COMPILE_CONSTRAINT_BONE_UNKNOWN"></a>`CE_COMPILE_CONSTRAINT_BONE_UNKNOWN` | “&lt;value&gt;: &lt;value&gt; names &lt;value&gt;, which the rig does not declare as a bone”<br>Also: “rig constraint "&lt;value&gt;"” | Use a constraint bone declared in the rig. |
7119
+ | <a id="CE_COMPILE_CONSTRAINT_ENUM_UNKNOWN"></a>`CE_COMPILE_CONSTRAINT_ENUM_UNKNOWN` | “&lt;value&gt;: &lt;value&gt; is &lt;value&gt;; known: &lt;value&gt; (only the first letter's case is free — the parser's enumValue uppercases that one character and nothing else, and an unresolved name becomes undefined without an error)”<br>Also: “rig constraint "&lt;value&gt;"”<br>Here the values named in the message include: “ChainScale”, “None”, “Fixed”, “Volume”, “Length”, “Tangent”, “Uniform”, “Percent”, “Proportional”. | Use the named allowed enum spelling; only its first letter's case is free. |
7120
+ | <a id="CE_COMPILE_CONSTRAINT_NUMBER_NONFINITE"></a>`CE_COMPILE_CONSTRAINT_NUMBER_NONFINITE` | “&lt;value&gt;: &lt;value&gt; is &lt;value&gt;, which is not a finite number”<br>Also: “rig constraint "&lt;value&gt;"” | Supply finite constraint field numbers. |
7121
+ | <a id="CE_COMPILE_CONSTRAINT_BONES_EMPTY"></a>`CE_COMPILE_CONSTRAINT_BONES_EMPTY` | “&lt;value&gt;: a &lt;value&gt; constraint needs a non-empty "bones" array”<br>Also: “rig constraint "&lt;value&gt;"” | Name at least one bone in the constraint bones array. |
7122
+ | <a id="CE_COMPILE_TRANSFORM_PROPERTY_UNKNOWN"></a>`CE_COMPILE_TRANSFORM_PROPERTY_UNKNOWN` | “&lt;value&gt;: properties has "&lt;value&gt;"; known: &lt;value&gt;”<br>Also: “, ”<br>“rig constraint "&lt;value&gt;"”<br>Here the values named in the message include: “y”, “x”, “scaleY”, “shearY”, “scaleX”, “rotate”. | Use a transform property named in the allowed list. |
7123
+ | <a id="CE_COMPILE_TRANSFORM_TO_PROPERTY_UNKNOWN"></a>`CE_COMPILE_TRANSFORM_TO_PROPERTY_UNKNOWN` | “&lt;value&gt;: properties.&lt;value&gt;.to has "&lt;value&gt;"; known: &lt;value&gt;”<br>Also: “, ”<br>“rig constraint "&lt;value&gt;"”<br>Here the values named in the message include: “y”, “x”, “scaleY”, “shearY”, “scaleX”, “rotate”. | Use a to property named in the allowed transform-property list. |
7124
+ | <a id="CE_COMPILE_CONSTRAINT_SLOT_UNKNOWN"></a>`CE_COMPILE_CONSTRAINT_SLOT_UNKNOWN` | “&lt;value&gt;: slot names &lt;value&gt;, which the rig does not declare as a slot”<br>Also: “rig constraint "&lt;value&gt;"” | Use a slot declared by the rig. |
7125
+ | <a id="CE_COMPILE_PATH_CONSTRAINT_SLOT_NO_PATH"></a>`CE_COMPILE_PATH_CONSTRAINT_SLOT_NO_PATH` | “&lt;value&gt;: slot "&lt;value&gt;" has no path attachment in any skin, so the constraint has no curve to follow — PathConstraint.update returns immediately unless the slot's attachment is a path, which means this constraint would load, report every mix it was given, and move nothing. Give that slot an attachment with "type": "path".”<br>Also: “rig constraint "&lt;value&gt;"” | Give the target slot a path attachment in a skin. |
7126
+ | <a id="CE_COMPILE_SLIDER_ANIMATION_MISSING"></a>`CE_COMPILE_SLIDER_ANIMATION_MISSING` | “&lt;value&gt;: a slider needs an "animation" — the animation it applies. Without one the parser's second pass over the constraints array throws `Slider animation not found`.”<br>Also: “rig constraint "&lt;value&gt;"” | Name the animation the slider applies. |
7127
+ | <a id="CE_COMPILE_SLIDER_ANIMATION_UNKNOWN"></a>`CE_COMPILE_SLIDER_ANIMATION_UNKNOWN` | “&lt;value&gt;: applies animation "&lt;value&gt;", which the motion spec does not declare[ (it declares: &lt;value&gt;) / (it declares none at all)]”<br>Also: “rig constraint "&lt;value&gt;"” | Use an animation declared by the motion spec. |
7128
+ | <a id="CE_COMPILE_SLIDER_ANIMATION_EDITOR_ORDER"></a>`CE_COMPILE_SLIDER_ANIMATION_EDITOR_ORDER` | “&lt;value&gt;: applies animation "&lt;value&gt;", which the Spine file lists at index &lt;value&gt; of its animations and the Spine editor sorts to index &lt;value&gt; — so an editor import repoints this slider to "&lt;value&gt;", in a file that still parses and gates green. A JSON object lists every array-index key (&lt;value&gt; here) before the rest, the editor re-sorts the animations into its own order on import, and a slider holds its animation by index (measured on Spine 4.3.26; AUTHORING R10). Rename &lt;value&gt; so no animation name is a plain non-negative integer — a prefix or a leading zero ("a&lt;value&gt;", "0&lt;value&gt;") puts the file's order and the editor's in step.”<br>Also: “rig constraint "&lt;value&gt;"” | Rename integer animation keys with a prefix or leading zero so editor and file indices agree. |
7129
+ | <a id="CE_COMPILE_SLIDER_BONE_PROPERTY_UNKNOWN"></a>`CE_COMPILE_SLIDER_BONE_PROPERTY_UNKNOWN` | “&lt;value&gt;: drives off bone "&lt;value&gt;" but its property is &lt;value&gt;; known: &lt;value&gt; (the parser throws on anything else)”<br>Also: “, ”<br>“rig constraint "&lt;value&gt;"”<br>Here the values named in the message include: “x”, “scaleY”, “shearY”, “scaleX”, “rotate”. | Use a driving property named in the allowed list. |
7130
+ | <a id="CE_COMPILE_SLIDER_SCALE_ZERO"></a>`CE_COMPILE_SLIDER_SCALE_ZERO` | “&lt;value&gt;: scale is 0, so the bone's property cannot move the slider's time at all”<br>Also: “rig constraint "&lt;value&gt;"” | Use a nonzero slider mapping scale. |
7131
+ | <a id="CE_COMPILE_SLIDER_WORLD_ROTATION_DEAD_RANGE"></a>`CE_COMPILE_SLIDER_WORLD_ROTATION_DEAD_RANGE` | “&lt;value&gt;: drives off bone "&lt;value&gt;" rotate with "local": false, and the driving values that reach animation "&lt;value&gt;" (0s..&lt;value&gt;s) run from &lt;value&gt;° to &lt;value&gt;°. A world rotation is read through `FromRotate.value`, which ends `if (value &lt; 0) value += 360`, so the bone at &lt;value&gt;° is read as &lt;value&gt;° and maps to time &lt;value&gt;s. &lt;value&gt; The whole part of the range &lt;value&gt; is dead and nothing at runtime reports it. Add `"local": true` to read the bone's own rotation signed and unwrapped — that is the form a face axis wants — or &lt;value&gt;.”<br>“&lt;value&gt;s..&lt;value&gt;s”<br>“[Nothing is held: "loop": true wraps the time as `duration + (time % duration)`, so the &lt;value&gt;° of the range &lt;value&gt; selects nothing a reading inside the circle does not already select. / [This dial reaches none of the animation's &lt;value&gt;s — the whole circle is held on the frame at &lt;value&gt;s. / [This dial reaches only &lt;value&gt; of the animation's &lt;value&gt;s, and no reading of the circle reaches the rest of it. / This dial reaches only &lt;value&gt; of the animation's &lt;value&gt;s, and &lt;value&gt;% of the circle — &lt;value&gt; — is held on the frame at &lt;value&gt;s.]]]”<br>“[every reading / [every reading below &lt;value&gt;° / every reading above &lt;value&gt;°]]”<br>“below 0°”<br>“move the range so it does not cross 0°”<br>“move the range so it does not run past 360°”<br>“past 360°”<br>Also: “{&lt;value&gt; of the range below 0 repeats 0.000..&lt;value&gt;, which is &lt;value&gt;s..&lt;value&gt;s of the animation, in reverse. / the whole &lt;value&gt; of this range is below 0, so it reaches none of the animation's &lt;value&gt;s — every value the reader can return maps past it and the pose holds the frame at &lt;value&gt;s.}”<br>“rig constraint "&lt;value&gt;"”<br>“rename so the only whitespace in either name is a space”<br>“write each number one way — rename so no digit run in either name has a second spelling”<br>“rename one of the two folders so they differ by more than letter case, spacing or a leading zero” | Set local true to read signed unwrapped rotation, or move the mapping outside the named dead range. |
7132
+ | <a id="CE_COMPILE_SLIDER_WORLD_SCALE_FOLDED"></a>`CE_COMPILE_SLIDER_WORLD_SCALE_FOLDED` | “&lt;value&gt;: drives off bone "&lt;value&gt;" &lt;value&gt; with "local": false, and the driving values that reach animation "&lt;value&gt;" (0s..&lt;value&gt;s) run from &lt;value&gt; to &lt;value&gt;. A world scale is read through `From[ScaleX / ScaleY].value` as `Math.sqrt([a² + c² / b² + d²])`, a magnitude, so the bone at &lt;value&gt; is read as &lt;value&gt; and maps to time &lt;value&gt;s — the time the bone at &lt;value&gt; maps to. Positions below 0 read as the mirror of positions above it: &lt;value&gt; Nothing at runtime reports it. Add `"local": true` to read the bone's own scale signed and unfolded — that is the form a squash axis wants — or move the range so it does not dip below 0.”<br>“[&lt;value&gt; of the range below 0 repeats 0.000..&lt;value&gt;, which is &lt;value&gt;s..&lt;value&gt;s of the animation, in reverse. / the whole &lt;value&gt; of this range is below 0, so it reaches none of the animation's &lt;value&gt;s — every value the reader can return maps past it and the pose holds the frame at &lt;value&gt;s.]”<br>Also: “{Nothing is held: "loop": true wraps the time as `duration + (time % duration)`, so the &lt;value&gt;° of the range &lt;value&gt; selects nothing a reading inside the circle does not already select. / {This dial reaches none of the animation's &lt;value&gt;s — the whole circle is held on the frame at &lt;value&gt;s. / {This dial reaches only &lt;value&gt; of the animation's &lt;value&gt;s, and no reading of the circle reaches the rest of it. / This dial reaches only &lt;value&gt; of the animation's &lt;value&gt;s, and &lt;value&gt;% of the circle — &lt;value&gt; — is held on the frame at &lt;value&gt;s.}}}”<br>“{every reading / {every reading below &lt;value&gt;° / every reading above &lt;value&gt;°}}”<br>“below 0°”<br>“past 360°”<br>“rig constraint "&lt;value&gt;"” | Set local true to read signed scale, or keep the mapped range at or above zero. |
7133
+ | <a id="CE_COMPILE_SLIDER_BONELESS_FIELD_WITH_BONE"></a>`CE_COMPILE_SLIDER_BONELESS_FIELD_WITH_BONE` | “&lt;value&gt;: declares both a "bone" and "&lt;value&gt;". A slider with a bone takes its time from that bone's property; "&lt;value&gt;" is read only by the bone-less form (`:361`), so it would be dropped in silence.”<br>Also: “rig constraint "&lt;value&gt;"” | Remove the bone-less-only field from the bone-driven slider. |
7134
+ | <a id="CE_COMPILE_SLIDER_BONE_FIELD_WITHOUT_BONE"></a>`CE_COMPILE_SLIDER_BONE_FIELD_WITHOUT_BONE` | “&lt;value&gt;: declares "&lt;value&gt;" but no "bone". Every one of &lt;value&gt; is read only inside the parser's `if (boneName)` branch (`:350-360`), so it would be dropped in silence. Name the driving bone, or key `slider.&lt;name&gt;.time` in the motion spec instead.”<br>Also: “rig constraint "&lt;value&gt;"”<br>Here the values named in the message include: “/”, “to”, “max”, “from”, “local”, “scale”, “property”. | Name the driving bone or remove bone-only fields and key slider time instead. |
7135
+ | <a id="CE_COMPILE_CONSTRAINT_TYPE_UNKNOWN"></a>`CE_COMPILE_CONSTRAINT_TYPE_UNKNOWN` | “&lt;value&gt;: constraint type &lt;value&gt; is not one Spine 4.3 knows. The five are: ik, transform, path, physics, slider. An unrecognised type matches no case in the parser and the constraint is dropped without a word.”<br>Also: “rig constraint "&lt;value&gt;"” | Use ik, transform, path, physics or slider as the constraint type. |
7136
+ | <a id="CE_COMPILE_AXIS_BONE_UNKNOWN"></a>`CE_COMPILE_AXIS_BONE_UNKNOWN` | “rig "&lt;value&gt;" names "&lt;value&gt;" as its axis bone, which it does not declare” | Declare the rig's axis bone or correct its name. |
7137
+ | <a id="CE_COMPILE_WINDING_EXEMPTION_NOT_MESH"></a>`CE_COMPILE_WINDING_EXEMPTION_NOT_MESH` | “rig "&lt;value&gt;" exempts slot "&lt;value&gt;" from A39_DEFORM_KEEPS_TRIANGLE_WINDING, but that slot carries no mesh — winding is a property of triangles, so there is nothing there to exempt” | Exempt only slots that carry meshes from triangle winding measurement. |
7138
+ | <a id="CE_COMPILE_CONTACT_DEPTH_INVALID"></a>`CE_COMPILE_CONTACT_DEPTH_INVALID` | “manifest stroke.contact_depth is &lt;value&gt;; it must be a positive number of axis pixels” | State positive manifest stroke.contact_depth in axis pixels. |
7139
+ | <a id="CE_COMPILE_CONTAINMENT_CEILING_INVALID"></a>`CE_COMPILE_CONTAINMENT_CEILING_INVALID` | “manifest stroke.cap_containment_ceiling is &lt;value&gt;; it must be a positive number of axis pixels (use null for "not measurable on this cut")” | State positive cap_containment_ceiling in axis pixels, or null when unmeasurable. |
7140
+ | <a id="CE_COMPILE_AXIS_UNIT_INVALID"></a>`CE_COMPILE_AXIS_UNIT_INVALID` | “manifest axis.unit must be [x, y], got &lt;value&gt;” | State axis.unit as an x/y pair. |
7141
+ | <a id="CE_COMPILE_AXIS_UNIT_DEG_MISMATCH"></a>`CE_COMPILE_AXIS_UNIT_DEG_MISMATCH` | “manifest axis.unit [&lt;value&gt;, &lt;value&gt;] does not match axis.deg &lt;value&gt; (expected [&lt;value&gt;, &lt;value&gt;])” | Make axis.unit agree with the unit vector derived from axis.deg. |
7142
+ | <a id="CE_COMPILE_INTERNAL_MESH_BONE_UNKNOWN"></a>`CE_COMPILE_INTERNAL_MESH_BONE_UNKNOWN` | “internal: mesh bone "&lt;value&gt;" is not in the bone list” | Report the mesh bone name and compiler defect: resolved geometry names a bone absent from the compiled bone list. |
7143
+ | <a id="CE_COMPILE_INTERNAL_MESH_BONE_TRANSFORM_MISSING"></a>`CE_COMPILE_INTERNAL_MESH_BONE_TRANSFORM_MISSING` | “internal: no setup transform for mesh bone "&lt;value&gt;"” | Report the mesh bone name and compiler defect: resolved geometry lost its setup transform. |
7144
+ | <a id="CE_COMPILE_INTERNAL_CONTROL_BONE_TRANSFORM_MISSING"></a>`CE_COMPILE_INTERNAL_CONTROL_BONE_TRANSFORM_MISSING` | “internal: no setup transform for control bone "&lt;value&gt;"” | Report the control bone name and compiler defect: the ring control lost its exact setup transform. |
7145
+ | <a id="CE_COMPILE_MANIFEST_RING_RIBBON_INVALID"></a>`CE_COMPILE_MANIFEST_RING_RIBBON_INVALID` | “a polygon vertex sits exactly on the aperture centre”<br>“a ring mesh needs at least one control bone”<br>“aperture centre (&lt;value&gt;,&lt;value&gt;) is outside the &lt;value&gt;x&lt;value&gt; part window”<br>“bad part size &lt;value&gt;x&lt;value&gt;”<br>“bias ramp must increase, got [&lt;value&gt;, &lt;value&gt;]”<br>“control bone "&lt;value&gt;" sits on the aperture centre, so it has no radial direction”<br>“hull is not star-shaped about the aperture centre; the inner ring would fold”<br>“hull needs at least 6 points, got &lt;value&gt;”<br>“hull point (&lt;value&gt;,&lt;value&gt;) is outside the &lt;value&gt;x&lt;value&gt; part window”<br>“inner must be in (0,1), got &lt;value&gt;”<br>“ray to the window edge did not converge”<br>“ribbon needs at least 3 rows, got &lt;value&gt;”<br>“ribbon needs at least one chain bone, got &lt;value&gt;”<br>“slot "&lt;value&gt;" mesh: &lt;value&gt;”<br>“two control bones share the angle &lt;value&gt; degrees about the aperture centre”<br>Also: “internal: no setup transform for control bone "&lt;value&gt;"” | Correct manifest ring/ribbon parameters and controls as the full generator message states. |
7146
+
7147
+
7148
+ #### 5.1.9 Motion keys, curves and target groups
7149
+
7150
+ | Code | Fixed message text and alternatives | What to change |
7151
+ | --- | --- | --- |
7152
+ | <a id="CE_COMPILE_CURVE_NOT_ARRAY"></a>`CE_COMPILE_CURVE_NOT_ARRAY` | “&lt;value&gt; (t=&lt;value&gt;): curve must be an array or "stepped"” | Use a numeric curve array or stepped. |
7153
+ | <a id="CE_COMPILE_CURVE_CHANNEL_COUNT"></a>`CE_COMPILE_CURVE_CHANNEL_COUNT` | “&lt;value&gt; (t=&lt;value&gt;): raw curve has &lt;value&gt; numbers, this timeline needs &lt;value&gt; channel(s) x 4 = &lt;value&gt;” | Supply four raw Bezier numbers per timeline channel. |
7154
+ | <a id="CE_COMPILE_CURVE_VALUE_NONFINITE"></a>`CE_COMPILE_CURVE_VALUE_NONFINITE` | “&lt;value&gt; (t=&lt;value&gt;): raw curve holds a non-finite value &lt;value&gt;” | Supply finite numbers in the raw curve array. |
7155
+ | <a id="CE_COMPILE_VALUE_TIMELINE_PROPERTY_UNKNOWN"></a>`CE_COMPILE_VALUE_TIMELINE_PROPERTY_UNKNOWN` | “animation "&lt;value&gt;": &lt;value&gt; "&lt;value&gt;" has no property "&lt;value&gt;"” | Use a property present on the named target's timeline family. |
7156
+ | <a id="CE_COMPILE_TIMELINE_KEYS_EMPTY"></a>`CE_COMPILE_TIMELINE_KEYS_EMPTY` | “&lt;value&gt;: no keys”<br>Also: “animation "&lt;value&gt;" deform &lt;value&gt;/&lt;value&gt;/&lt;value&gt;”<br>“animation "&lt;value&gt;" events”<br>“animation "&lt;value&gt;" drawOrder”<br>“animation "&lt;value&gt;" slot "&lt;value&gt;" &lt;value&gt;”<br>“animation "&lt;value&gt;" &lt;value&gt; constraint "&lt;value&gt;"”<br>Here the values named in the message include: “default”. | Supply at least one key in the timeline. |
7157
+ | <a id="CE_COMPILE_KEY_TIMES_NOT_INCREASING"></a>`CE_COMPILE_KEY_TIMES_NOT_INCREASING` | “&lt;value&gt;: key times must strictly increase (at t=&lt;value&gt;)”<br>Also: “animation "&lt;value&gt;" deform &lt;value&gt;/&lt;value&gt;/&lt;value&gt;”<br>“animation "&lt;value&gt;" drawOrder”<br>“animation "&lt;value&gt;" slot "&lt;value&gt;" &lt;value&gt;”<br>“animation "&lt;value&gt;" &lt;value&gt; constraint "&lt;value&gt;"”<br>Here the values named in the message include: “default”. | Order keys by strictly increasing time. |
7158
+ | <a id="CE_COMPILE_STEPPED_TIMELINE_EASING"></a>`CE_COMPILE_STEPPED_TIMELINE_EASING` | “&lt;value&gt; key at t=&lt;value&gt; carries [an easing ("&lt;value&gt;") / a curve], and this timeline is stepped by the format — its reader builds no curve, so the mode changes AT the key and holds until the next one. Remove it”<br>Also: “animation "&lt;value&gt;" &lt;value&gt; "&lt;value&gt;" &lt;value&gt;” | Remove easing/curve from the stepped mode timeline. |
7159
+ | <a id="CE_COMPILE_TIMELINE_MODE_UNKNOWN"></a>`CE_COMPILE_TIMELINE_MODE_UNKNOWN` | “&lt;value&gt; key at t=&lt;value&gt; names mode &lt;value&gt;; &lt;value&gt;”<br>“known: &lt;value&gt; — the runtime folds the case of the first letter and of nothing else”<br>Also: “animation "&lt;value&gt;" &lt;value&gt; "&lt;value&gt;" &lt;value&gt;”<br>“, ”<br>Here the values named in the message include: “noScaleOrReflection”, “normal”, “onlyTranslation”, “noRotationOrReflection”. | Use a mode named in the timeline's allowed mode list. |
7160
+ | <a id="CE_COMPILE_VALUELESS_TIMELINE_VALUE"></a>`CE_COMPILE_VALUELESS_TIMELINE_VALUE` | “&lt;value&gt;: this timeline takes no value; use null”<br>Also: “animation "&lt;value&gt;" &lt;value&gt; "&lt;value&gt;" &lt;value&gt;” | Use null for a timeline that takes no value. |
7161
+ | <a id="CE_COMPILE_EVENT_TIMELINE_EASING"></a>`CE_COMPILE_EVENT_TIMELINE_EASING` | “&lt;value&gt;: an event timeline cannot carry an easing”<br>Also: “animation "&lt;value&gt;" &lt;value&gt; "&lt;value&gt;" &lt;value&gt;” | Remove easing from the event timeline. |
7162
+ | <a id="CE_COMPILE_TIMELINE_VALUE_CHANNEL_COUNT"></a>`CE_COMPILE_TIMELINE_VALUE_CHANNEL_COUNT` | “&lt;value&gt;: key value must be an array of &lt;value&gt; number(s)”<br>Also: “animation "&lt;value&gt;" &lt;value&gt; "&lt;value&gt;" &lt;value&gt;” | Supply the named number of numeric channels in every key value array. |
7163
+ | <a id="CE_COMPILE_TIMELINE_VALUE_NONFINITE"></a>`CE_COMPILE_TIMELINE_VALUE_NONFINITE` | “&lt;value&gt;: non-finite value &lt;value&gt;”<br>Also: “animation "&lt;value&gt;" &lt;value&gt; "&lt;value&gt;" &lt;value&gt;” | Supply finite key value numbers. |
7164
+ | <a id="CE_COMPILE_PHYSICS_KEY_RANGE_INVALID"></a>`CE_COMPILE_PHYSICS_KEY_RANGE_INVALID` | “&lt;value&gt; &lt;value&gt; is &lt;value&gt;”<br>“&lt;value&gt;. 0 is a key the runtime has a branch for: `update` returns immediately (`PhysicsConstraint.js:109-111`), which mutes the constraint for the span”<br>“&lt;value&gt;. It is the restoring force, `velocity += (a - offset * strength) * m` (`PhysicsConstraint.js:150,156,212,220`), and a multiplicand everywhere it is read. 0 is a key the runtime plays: it releases the constraint for the span, damping and inertia still apply, and the next key pulls the offset back”<br>“&lt;value&gt;; &lt;value&gt;”<br>“&lt;value&gt;&lt;value&gt;; must be &lt;value&gt; — &lt;value&gt;”<br>“&gt; 0”<br>“&gt;= 0”<br>“[ / (&lt;value&gt; &lt;value&gt;)]”<br>“[&lt;value&gt; (`&lt;value&gt;`) / the runtime runs this value finitely, so refusing it is rigc's call rather than the runtime's: &lt;value&gt;]”<br>“above 1 every velocity grows on every step and the offset diverges”<br>“at 0 `massInverse = 1 / mass` is Infinity and `m = t * massInverse` multiplies every velocity update, so the first step takes every velocity and offset to NaN”<br>“at 0 `update` returns before it does anything (`PhysicsConstraint.js:109-111`), so the constraint is muted”<br>“at 1 the per-step decay is 1 at every rate, so no velocity ever decays: the step's two eigenvalues lie ON the unit circle (modulus √1 = 1) rather than inside it, so nothing a push puts in (wind, gravity, a key, the bone moving) ever dies out, and two such constraints on one chain stepping alike resonate and grow without limit”<br>“at any fps where `60 / fps` is not whole it is a negative number raised to a fractional power, which is NaN”<br>“below 0 `massInverse` is a finite negative, which flips the sign of every force the velocity update applies, so the restoring force pushes the offset away and it grows with every step”<br>“below 0 the jiggle is applied inverted, on `x` and `y` exactly the offset a positive mix of the same size applies, mirrored (`PhysicsConstraint.js:172,174`), and `PhysicsConstraintPose` documents mix as "a percentage (0+)" where a transform constraint documents its own as "unbounded"”<br>“inside [0, 1)”<br>“the per-step decay is `damping ** (60 * step)`, with `step` = 1 / the constraint's `fps`, and every velocity is multiplied by it (`PhysicsConstraint.js:114,148,158,163,210,222,227`), so &lt;value&gt;, at every rate — finite on every step until the velocity overflows, so refusing it is rigc's call rather than the runtime's. Below 0 the result depends on `fps`: where `60 / fps` is a whole number a negative base stays finite — at 60 fps it is the velocity's sign flipped each step, which can look like a jiggle settling — and &lt;value&gt; (`(-0.5) ** (60 / 45)`), so a rig tried only at 60 fps never shows the failure. And &lt;value&gt; — finite on every step as well, so that refusal is rigc's call too. 0 is inside: at 0 every velocity is zeroed on every step, so the offset follows the bone with no overshoot”<br>Also: “{&lt;value&gt; at t=&lt;value&gt; / key at t=&lt;value&gt;}”<br>“below 0 the restoring term is ADDED to the offset instead of taken out of it, so the offset is pushed away and grows with every step”<br>“nothing pulls it back”<br>“animation "&lt;value&gt;" &lt;value&gt; "&lt;value&gt;" &lt;value&gt;”<br>“SkeletonJson.js:309, Animation.js:2140, PhysicsConstraint.js:149,156,211” | Use physics values within the full message's documented bounds; positive mass and global property rules are not defaults. |
7165
+ | <a id="CE_COMPILE_KEY_EASING_AND_CURVE"></a>`CE_COMPILE_KEY_EASING_AND_CURVE` | “&lt;value&gt;: a key carries both a named easing and a raw curve; pick one”<br>Also: “animation "&lt;value&gt;" slot "&lt;value&gt;" &lt;value&gt;”<br>“animation "&lt;value&gt;" &lt;value&gt; constraint "&lt;value&gt;"” | Choose a named easing or a raw curve on the key. |
7166
+ | <a id="CE_COMPILE_LAST_KEY_CURVE"></a>`CE_COMPILE_LAST_KEY_CURVE` | “&lt;value&gt;: last key carries a curve but has nothing to ease to”<br>Also: “animation "&lt;value&gt;" slot "&lt;value&gt;" &lt;value&gt;”<br>“animation "&lt;value&gt;" &lt;value&gt; constraint "&lt;value&gt;"” | Remove the last key's curve or supply a following key. |
7167
+ | <a id="CE_COMPILE_KEY_EASING_UNKNOWN"></a>`CE_COMPILE_KEY_EASING_UNKNOWN` | “&lt;value&gt;: unknown easing "&lt;value&gt;"”<br>Also: “animation "&lt;value&gt;" slot "&lt;value&gt;" &lt;value&gt;”<br>“animation "&lt;value&gt;" &lt;value&gt; constraint "&lt;value&gt;"” | Use a named easing supported by the motion format. |
7168
+ | <a id="CE_COMPILE_NEXT_KEY_VALUE_NOT_ARRAY"></a>`CE_COMPILE_NEXT_KEY_VALUE_NOT_ARRAY` | “&lt;value&gt;: next key value must be an array”<br>Also: “animation "&lt;value&gt;" &lt;value&gt; "&lt;value&gt;" &lt;value&gt;” | Supply the next key's value as a numeric array. |
7169
+ | <a id="CE_COMPILE_LAST_KEY_EASING"></a>`CE_COMPILE_LAST_KEY_EASING` | “&lt;value&gt;: last key carries an easing but has nothing to ease to”<br>Also: “animation "&lt;value&gt;" slot "&lt;value&gt;" &lt;value&gt;”<br>“animation "&lt;value&gt;" &lt;value&gt; constraint "&lt;value&gt;"” | Remove the last key's easing or supply a following key. |
7170
+ | <a id="CE_COMPILE_DRAW_ORDER_SLOT_UNKNOWN"></a>`CE_COMPILE_DRAW_ORDER_SLOT_UNKNOWN` | “&lt;value&gt; at t=&lt;value&gt;: slot "&lt;value&gt;" is not one this rig emits”<br>Also: “animation "&lt;value&gt;" drawOrder” | Name a slot this rig emits. |
7171
+ | <a id="CE_COMPILE_DRAW_ORDER_SLOT_DUPLICATE"></a>`CE_COMPILE_DRAW_ORDER_SLOT_DUPLICATE` | “&lt;value&gt; at t=&lt;value&gt;: slot "&lt;value&gt;" is offset twice in one key”<br>Also: “animation "&lt;value&gt;" drawOrder” | Offset each slot at most once per draw-order key. |
7172
+ | <a id="CE_COMPILE_DRAW_ORDER_OFFSET_NONINTEGER"></a>`CE_COMPILE_DRAW_ORDER_OFFSET_NONINTEGER` | “&lt;value&gt; at t=&lt;value&gt;: slot "&lt;value&gt;" offset &lt;value&gt; is not a whole number”<br>Also: “animation "&lt;value&gt;" drawOrder” | State each draw-order offset as a whole number. |
7173
+ | <a id="CE_COMPILE_DRAW_ORDER_OFFSET_OUTSIDE_SLOTS"></a>`CE_COMPILE_DRAW_ORDER_OFFSET_OUTSIDE_SLOTS` | “&lt;value&gt; at t=&lt;value&gt;: slot "&lt;value&gt;" is at index &lt;value&gt; and offset &lt;value&gt; puts it at &lt;value&gt;, outside the &lt;value&gt; emitted slots”<br>Also: “animation "&lt;value&gt;" drawOrder” | Keep the offset destination within the emitted slot array. |
7174
+ | <a id="CE_COMPILE_EVENT_KEY_NAME_MISSING"></a>`CE_COMPILE_EVENT_KEY_NAME_MISSING` | “&lt;value&gt;: key &lt;value&gt; has no "name"; an event key fires an event by name”<br>Also: “animation "&lt;value&gt;" events” | Name the event fired by this key. |
7175
+ | <a id="CE_COMPILE_EVENT_KEY_EVENT_UNKNOWN"></a>`CE_COMPILE_EVENT_KEY_EVENT_UNKNOWN` | “&lt;value&gt; at t=&lt;value&gt;: event "&lt;value&gt;" is not declared in the rig spec's "events" block; [declared: &lt;value&gt; / that block is empty or absent]”<br>Also: “animation "&lt;value&gt;" events”<br>“, ” | Declare the event in the rig events block or correct its name. |
7176
+ | <a id="CE_COMPILE_EVENT_KEY_TIMES_BACKWARDS"></a>`CE_COMPILE_EVENT_KEY_TIMES_BACKWARDS` | “&lt;value&gt;: key times must not go backwards (at t=&lt;value&gt;, after t=&lt;value&gt;) — the parser writes frames in array order and never sorts them”<br>Also: “animation "&lt;value&gt;" events” | Order event keys without moving backwards in time. |
7177
+ | <a id="CE_COMPILE_EVENT_KEY_INT_INVALID"></a>`CE_COMPILE_EVENT_KEY_INT_INVALID` | “&lt;value&gt; at t=&lt;value&gt;: int &lt;value&gt; is not an integer”<br>Also: “animation "&lt;value&gt;" events” | State event int overrides as integers. |
7178
+ | <a id="CE_COMPILE_EVENT_KEY_FLOAT_NONFINITE"></a>`CE_COMPILE_EVENT_KEY_FLOAT_NONFINITE` | “&lt;value&gt; at t=&lt;value&gt;: float &lt;value&gt; is not finite”<br>Also: “animation "&lt;value&gt;" events” | State event float overrides as finite numbers. |
7179
+ | <a id="CE_COMPILE_EVENT_KEY_STRING_INVALID"></a>`CE_COMPILE_EVENT_KEY_STRING_INVALID` | “&lt;value&gt; at t=&lt;value&gt;: string &lt;value&gt; is not a string”<br>Also: “animation "&lt;value&gt;" events” | State event string overrides as strings. |
7180
+ | <a id="CE_COMPILE_EVENT_AUDIO_OVERRIDE_NO_AUDIO"></a>`CE_COMPILE_EVENT_AUDIO_OVERRIDE_NO_AUDIO` | “&lt;value&gt; at t=&lt;value&gt;: &lt;value&gt; is set but event "&lt;value&gt;" declares no "audio"; the parser reads &lt;value&gt; only for an event with an audio path, so it would be dropped in silence”<br>Also: “animation "&lt;value&gt;" events” | Declare the event audio path or remove audio-only overrides. |
7181
+ | <a id="CE_COMPILE_EVENT_AUDIO_NUMBER_NONFINITE"></a>`CE_COMPILE_EVENT_AUDIO_NUMBER_NONFINITE` | “&lt;value&gt; at t=&lt;value&gt;: &lt;value&gt; &lt;value&gt; is not finite”<br>Also: “animation "&lt;value&gt;" events” | State finite event audio override numbers. |
7182
+ | <a id="CE_COMPILE_CONSTRAINT_KEY_FIELD_ADDED"></a>`CE_COMPILE_CONSTRAINT_KEY_FIELD_ADDED` | “&lt;value&gt;: key &lt;value&gt; (t=&lt;value&gt;) names "&lt;value&gt;" and key 0 does not. Every key of &lt;value&gt; &lt;value&gt; timeline is read with its own default, so a field stated on some keys and not others snaps to the default on the rest — state it on every key or on none.”<br>Also: “animation "&lt;value&gt;" &lt;value&gt; constraint "&lt;value&gt;"” | State this constraint field on every key or on none. |
7183
+ | <a id="CE_COMPILE_CONSTRAINT_KEY_FIELD_OMITTED"></a>`CE_COMPILE_CONSTRAINT_KEY_FIELD_OMITTED` | “&lt;value&gt;: key 0 names "&lt;value&gt;" and key &lt;value&gt; (t=&lt;value&gt;) does not. Every key of &lt;value&gt; &lt;value&gt; timeline is read with its own default, so "&lt;value&gt;" would snap to &lt;value&gt; at t=&lt;value&gt; — state it on every key or on none.”<br>Also: “animation "&lt;value&gt;" &lt;value&gt; constraint "&lt;value&gt;"” | State this constraint field on every key or on none. |
7184
+ | <a id="CE_COMPILE_CONSTRAINT_KEY_NUMBER_NONFINITE"></a>`CE_COMPILE_CONSTRAINT_KEY_NUMBER_NONFINITE` | “&lt;value&gt; (t=&lt;value&gt;): &lt;value&gt; is &lt;value&gt;, not a finite number”<br>Also: “animation "&lt;value&gt;" &lt;value&gt; constraint "&lt;value&gt;"” | Supply finite constraint channel values. |
7185
+ | <a id="CE_COMPILE_CONSTRAINT_KEY_RANGE_INVALID"></a>`CE_COMPILE_CONSTRAINT_KEY_RANGE_INVALID` | “&lt;value&gt; (t=&lt;value&gt;): &lt;value&gt; is &lt;value&gt;, outside &lt;value&gt;..[∞ / &lt;value&gt;] — the runtime documents it as [a percentage 0-1 / a distance]”<br>Also: “animation "&lt;value&gt;" &lt;value&gt; constraint "&lt;value&gt;"” | Keep constraint channels in their documented percentage/distance bounds. |
7186
+ | <a id="CE_COMPILE_CONSTRAINT_KEY_FLAG_NOT_BOOLEAN"></a>`CE_COMPILE_CONSTRAINT_KEY_FLAG_NOT_BOOLEAN` | “&lt;value&gt; (t=&lt;value&gt;): &lt;value&gt; is &lt;value&gt;, not true or false”<br>Also: “animation "&lt;value&gt;" &lt;value&gt; constraint "&lt;value&gt;"” | State constraint flags as true or false. |
7187
+ | <a id="CE_COMPILE_DEFORM_ATTACHMENT_TYPE_INVALID"></a>`CE_COMPILE_DEFORM_ATTACHMENT_TYPE_INVALID` | “&lt;value&gt;: a deform timeline keys the vertices of an attachment, and this one is a "&lt;value&gt;" — it has no vertex array to deform. Deformable types: mesh, boundingbox, clipping, path.” | Target a mesh, boundingbox, clipping or path attachment with vertices. |
7188
+ | <a id="CE_COMPILE_DEFORM_WEIGHT_BONE_COUNT_INVALID"></a>`CE_COMPILE_DEFORM_WEIGHT_BONE_COUNT_INVALID` | “&lt;value&gt;: the attachment's weighted vertex run has a bone count of &lt;value&gt; at index &lt;value&gt;” | Correct the attachment's raw weighted run bone counts. |
7189
+ | <a id="CE_COMPILE_SEQUENCE_ATTACHMENT_NO_SERIES"></a>`CE_COMPILE_SEQUENCE_ATTACHMENT_NO_SERIES` | “&lt;value&gt;: attachment "&lt;value&gt;" carries no "sequence" block, so there is no series to step. The parser gives every region and mesh a series of ONE region (`readSequence(null)` is `new Sequence(1, false)`), so this timeline would load and show that region under every mode at every time. Give the attachment a "sequence" in the rig spec, or remove the track.” | Give the attachment a sequence block or remove the sequence track. |
7190
+ | <a id="CE_COMPILE_SEQUENCE_LINK_TIMELINE_INERT"></a>`CE_COMPILE_SEQUENCE_LINK_TIMELINE_INERT` | “&lt;value&gt;: attachment "&lt;value&gt;" is a linked mesh that plays its source's timelines ("timelines" is not false), so its `timelineAttachment` is "&lt;value&gt;" (`SkeletonJson.js:437-448`) and `SequenceTimeline` applies only where the slot's attachment's `timelineAttachment` is the one it was built for — a key aimed at the link is applied to nothing. Key "&lt;value&gt;" instead (the link steps its own series by it), or set "timelines": false on the link.” | Key the linked mesh's source or set timelines false on the link. |
7191
+ | <a id="CE_COMPILE_SEQUENCE_KEY_INDEX_OUTSIDE_SERIES"></a>`CE_COMPILE_SEQUENCE_KEY_INDEX_OUTSIDE_SERIES` | “&lt;value&gt; (t=&lt;value&gt;): index &lt;value&gt; is past the end of a &lt;value&gt;-frame series (frames 0 to &lt;value&gt;). `Sequence.resolveIndex` clamps it to the last frame, so the key would start on a frame it does not name. `index` is 0-based.” | Use a zero-based index within the frame series. |
7192
+ | <a id="CE_COMPILE_DEFORM_TRANSFORM_AND_VERTICES"></a>`CE_COMPILE_DEFORM_TRANSFORM_AND_VERTICES` | “&lt;value&gt; (t=&lt;value&gt;): the key carries both a "transform" and a "vertices" run, and they are two answers to one question. Authored offsets and a stated model do not combine, for the same reason a mesh cannot carry both a "generator" and authored geometry — drop one.”<br>Also: “animation "&lt;value&gt;" deform &lt;value&gt;/&lt;value&gt;/&lt;value&gt;”<br>Here the values named in the message include: “default”. | Use a transform model or authored vertex offsets. |
7193
+ | <a id="CE_COMPILE_DEFORM_TRANSFORM_START_INDEX"></a>`CE_COMPILE_DEFORM_TRANSFORM_START_INDEX` | “&lt;value&gt; (t=&lt;value&gt;): the key states a "transform" and a start index. A transform is a model of the whole attachment and is evaluated over all &lt;value&gt; of its vertices, so it always starts at deform index 0. A model applied to part of a run leaves a step at the run's edge — write the partial run by hand if that is what you mean.”<br>Also: “animation "&lt;value&gt;" deform &lt;value&gt;/&lt;value&gt;/&lt;value&gt;”<br>Here the values named in the message include: “default”. | Apply a transform over the whole attachment without a start index, or author the partial run. |
7194
+ | <a id="CE_COMPILE_DEFORM_TRANSFORM_SETUP_UNRESOLVED"></a>`CE_COMPILE_DEFORM_TRANSFORM_SETUP_UNRESOLVED` | “&lt;value&gt; (t=&lt;value&gt;): a "transform" states where every vertex of this attachment goes, and this one has a vertex the arithmetic cannot place — &lt;value&gt;. Fix the weights, or write the bind-space pairs yourself and start the run with "offset".”<br>“vertex &lt;value&gt;'s &lt;value&gt; weights sum to &lt;value&gt; rather than 1. A stated model becomes a deform run by writing each vertex's world displacement D into every influence as Mᵢ⁻¹·D, which moves the vertex by D·Σwᵢ — so a sum that is not 1 has no displacement that lands it where the model says. A20_MESH_WEIGHTS_COHERENT is the assertion that requires that sum, at the same 1e-3”<br>Also: “animation "&lt;value&gt;" deform &lt;value&gt;/&lt;value&gt;/&lt;value&gt;”<br>Here the values named in the message include: “default”. | Fix weights so setup vertices can be positioned, or author bind-space pairs using offset. |
7195
+ | <a id="CE_COMPILE_DEFORM_TRANSFORM_OFFSET_COUNT"></a>`CE_COMPILE_DEFORM_TRANSFORM_OFFSET_COUNT` | “&lt;value&gt; (t=&lt;value&gt;): the transform produced &lt;value&gt; numbers for &lt;value&gt; vertices”<br>Also: “animation "&lt;value&gt;" deform &lt;value&gt;/&lt;value&gt;/&lt;value&gt;”<br>Here the values named in the message include: “default”. | Report the transform model and compiler defect: the produced offset count does not match the vertices. |
7196
+ | <a id="CE_COMPILE_DEFORM_TRANSFORM_RUN_LENGTH"></a>`CE_COMPILE_DEFORM_TRANSFORM_RUN_LENGTH` | “&lt;value&gt; (t=&lt;value&gt;): the transform expanded to &lt;value&gt; numbers and this attachment's deform array is &lt;value&gt; long”<br>Also: “animation "&lt;value&gt;" deform &lt;value&gt;/&lt;value&gt;/&lt;value&gt;”<br>Here the values named in the message include: “default”. | Report the transform model and compiler defect: the expanded offsets do not match the deform array. |
7197
+ | <a id="CE_COMPILE_DEFORM_START_SOURCES_CONFLICT"></a>`CE_COMPILE_DEFORM_START_SOURCES_CONFLICT` | “&lt;value&gt; (t=&lt;value&gt;): a key gives its start as "offset" (an index into the deform array) or as "fromVertex" (a vertex index rigc translates), never both”<br>Also: “animation "&lt;value&gt;" deform &lt;value&gt;/&lt;value&gt;/&lt;value&gt;”<br>Here the values named in the message include: “default”. | Use offset or fromVertex, rather than both. |
7198
+ | <a id="CE_COMPILE_DEFORM_SETUP_KEY_START_INDEX"></a>`CE_COMPILE_DEFORM_SETUP_KEY_START_INDEX` | “&lt;value&gt; (t=&lt;value&gt;): the key has no "vertices", which is the format's way of saying "back to the setup pose" — so there is nothing for a start index to point at. Drop the offset, or give it a run.”<br>Also: “animation "&lt;value&gt;" deform &lt;value&gt;/&lt;value&gt;/&lt;value&gt;”<br>Here the values named in the message include: “default”. | Drop the start index on a setup-pose key or supply a vertices run. |
7199
+ | <a id="CE_COMPILE_DEFORM_VERTICES_NOT_ARRAY"></a>`CE_COMPILE_DEFORM_VERTICES_NOT_ARRAY` | “&lt;value&gt; (t=&lt;value&gt;): "vertices" is &lt;value&gt;; give an array of x, y offsets, or omit it entirely for "back to the setup pose"”<br>Also: “animation "&lt;value&gt;" deform &lt;value&gt;/&lt;value&gt;/&lt;value&gt;”<br>Here the values named in the message include: “default”. | Supply x/y offset pairs or omit vertices to restore setup pose. |
7200
+ | <a id="CE_COMPILE_DEFORM_VERTEX_VALUE_NONFINITE"></a>`CE_COMPILE_DEFORM_VERTEX_VALUE_NONFINITE` | “&lt;value&gt; (t=&lt;value&gt;): "vertices" holds a non-finite value &lt;value&gt;”<br>Also: “animation "&lt;value&gt;" deform &lt;value&gt;/&lt;value&gt;/&lt;value&gt;”<br>Here the values named in the message include: “default”. | Supply finite numbers in the deform vertices array. |
7201
+
7202
+
7203
+ #### 5.1.10 Motion keys, curves and target groups (2)
7204
+
7205
+ | Code | Fixed message text and alternatives | What to change |
7206
+ | --- | --- | --- |
7207
+ | <a id="CE_COMPILE_DEFORM_RUN_OUTSIDE_ATTACHMENT"></a>`CE_COMPILE_DEFORM_RUN_OUTSIDE_ATTACHMENT` | “&lt;value&gt; (t=&lt;value&gt;): the run starts at deform index &lt;value&gt; and is &lt;value&gt; long, which ends at &lt;value&gt;&lt;value&gt;; this attachment's deform array is &lt;value&gt; long ([&lt;value&gt; bone influences / &lt;value&gt; vertices]). The parser copies into a Float32Array, so everything past the end is dropped without a word.”<br>Also: “animation "&lt;value&gt;" deform &lt;value&gt;/&lt;value&gt;/&lt;value&gt;”<br>Here the values named in the message include: “default”. | Keep the start and run length inside the attachment's deform array. |
7208
+ | <a id="CE_COMPILE_DEFORM_OFFSET_INVALID"></a>`CE_COMPILE_DEFORM_OFFSET_INVALID` | “&lt;value&gt; (t=&lt;value&gt;): offset is &lt;value&gt;; it is an index into the deform array, so a whole number ≥ 0” | State offset as a whole deform-array index at least zero. |
7209
+ | <a id="CE_COMPILE_DEFORM_FROM_VERTEX_INVALID"></a>`CE_COMPILE_DEFORM_FROM_VERTEX_INVALID` | “&lt;value&gt; (t=&lt;value&gt;): fromVertex is &lt;value&gt;; it is a vertex index, so a whole number ≥ 0” | State fromVertex as a whole vertex index at least zero. |
7210
+ | <a id="CE_COMPILE_DEFORM_FROM_VERTEX_OUTSIDE_ATTACHMENT"></a>`CE_COMPILE_DEFORM_FROM_VERTEX_OUTSIDE_ATTACHMENT` | “&lt;value&gt; (t=&lt;value&gt;): fromVertex &lt;value&gt; plus &lt;value&gt; vertex offset(s) runs to vertex &lt;value&gt;&lt;value&gt;, and the attachment has &lt;value&gt;” | Keep fromVertex plus the covered vertex count within the attachment. |
7211
+ | <a id="CE_COMPILE_DEFORM_WEIGHTED_FROM_VERTEX_AMBIGUOUS"></a>`CE_COMPILE_DEFORM_WEIGHTED_FROM_VERTEX_AMBIGUOUS` | “&lt;value&gt; (t=&lt;value&gt;): "fromVertex" counts VERTICES, and this attachment is weighted — its deform array holds one x, y pair per bone INFLUENCE, and vertex &lt;value&gt; has &lt;value&gt; of them. One offset per vertex is not a thing that array can hold: the world offset of a multi-bone vertex is the weighted sum of a per-bone offset in each bone's own bind space, so rigc will not guess one for you. Either key the control bone instead, or write the bind-space pairs yourself and start the run with "offset" (vertex &lt;value&gt; starts at deform index &lt;value&gt;).” | Key the control bone or author each bone influence's bind-space pair using offset. |
7212
+ | <a id="CE_COMPILE_TRACK_TARGETS_MULTIPLE"></a>`CE_COMPILE_TRACK_TARGETS_MULTIPLE` | “animation "&lt;value&gt;": a track names more than one target (&lt;value&gt;); the list is &lt;value&gt; and a track names exactly one”<br>Also: “, ”<br>Here the values named in the message include: “/”, “bone”, “slot”, “group”. | Name exactly one target field on a track. |
7213
+ | <a id="CE_COMPILE_CONSTRAINT_TRACK_PROPERTY_UNKNOWN"></a>`CE_COMPILE_CONSTRAINT_TRACK_PROPERTY_UNKNOWN` | “animation "&lt;value&gt;": &lt;value&gt; has no timeline "&lt;value&gt;" (it has: &lt;value&gt;)”<br>Also: “, ”<br>“path constraint”<br>“physics constraint”<br>“{group "&lt;value&gt;" / &lt;value&gt; "&lt;value&gt;"}”<br>Here the values named in the message include: “slider”. | Use a timeline property supported by this constraint family. |
7214
+ | <a id="CE_COMPILE_ANIMATION_GROUP_UNKNOWN"></a>`CE_COMPILE_ANIMATION_GROUP_UNKNOWN` | “animation "&lt;value&gt;": unknown group "&lt;value&gt;"” | Declare the motion group or correct its name. |
7215
+ | <a id="CE_COMPILE_CONSTRAINT_TRACK_TARGET_MISSING"></a>`CE_COMPILE_CONSTRAINT_TRACK_TARGET_MISSING` | “animation "&lt;value&gt;": "&lt;value&gt;" is a &lt;value&gt; timeline, and this track names no constraint — put the name in "&lt;value&gt;"”<br>Also: “ / ”<br>“" or "” | Name the constraint in the timeline's owning family field. |
7216
+ | <a id="CE_COMPILE_BONE_TRACK_TARGET_MISSING"></a>`CE_COMPILE_BONE_TRACK_TARGET_MISSING` | “animation "&lt;value&gt;": "&lt;value&gt;" is a bone track but no bone is named” | Name the track's bone target. |
7217
+ | <a id="CE_COMPILE_BONE_TRACK_PROPERTY_UNKNOWN"></a>`CE_COMPILE_BONE_TRACK_PROPERTY_UNKNOWN` | “animation "&lt;value&gt;" bone "&lt;value&gt;" has no timeline "&lt;value&gt;" (it has: &lt;value&gt;)[. "&lt;value&gt;" is a slot timeline — put the name in "slot" / ]”<br>Also: “, ” | Use a bone timeline property, or target a slot for slot properties. |
7218
+ | <a id="CE_COMPILE_GROUP_TRACK_PROPERTY_UNKNOWN"></a>`CE_COMPILE_GROUP_TRACK_PROPERTY_UNKNOWN` | “animation "&lt;value&gt;" group "&lt;value&gt;" has no timeline "&lt;value&gt;" (a bone group has: &lt;value&gt;; a slot group has: &lt;value&gt;; a &lt;value&gt; group has: &lt;value&gt;)”<br>Also: “, ” | Use a timeline property supported by this group's target family. |
7219
+ | <a id="CE_COMPILE_TRACK_TARGET_MISSING"></a>`CE_COMPILE_TRACK_TARGET_MISSING` | “animation "&lt;value&gt;": a track targets neither slot nor group” | Name a slot, bone, group or constraint target. |
7220
+ | <a id="CE_COMPILE_GROUP_MEMBERS_NOT_ARRAY"></a>`CE_COMPILE_GROUP_MEMBERS_NOT_ARRAY` | “group "&lt;value&gt;" is &lt;value&gt;; it is an array of member names” | State group members as an array of names. |
7221
+ | <a id="CE_COMPILE_GROUP_MEMBERS_EMPTY"></a>`CE_COMPILE_GROUP_MEMBERS_EMPTY` | “group "&lt;value&gt;" declares no members, so every track naming it would compile no timeline and gate green” | Name at least one member so the group emits timelines. |
7222
+ | <a id="CE_COMPILE_GROUP_MEMBER_NOT_NAME"></a>`CE_COMPILE_GROUP_MEMBER_NOT_NAME` | “group "&lt;value&gt;" member &lt;value&gt; is &lt;value&gt;; it is a bone or slot name” | State each group member as a bone or slot name. |
7223
+ | <a id="CE_COMPILE_GROUP_MEMBER_DUPLICATE"></a>`CE_COMPILE_GROUP_MEMBER_DUPLICATE` | “group "&lt;value&gt;" names member "&lt;value&gt;" twice (at index &lt;value&gt; and &lt;value&gt;). Member order is what `stagger` counts and what a per-member value map is read against, so a repeat is two different delays and two different values for one bone.” | List every group member once so stagger and value maps have one result per target. |
7224
+ | <a id="CE_COMPILE_MEMBER_VALUES_TARGET_UNNAMED"></a>`CE_COMPILE_MEMBER_VALUES_TARGET_UNNAMED` | “&lt;value&gt;: per-member values need a target whose members are named — put them on a track that names a "group", or a "bone" for the one-member case”<br>Also: “animation "&lt;value&gt;" &lt;value&gt; "&lt;value&gt;" &lt;value&gt;” | Use a named group target for per-member values, or a bone for a direct one-member value. |
7225
+ | <a id="CE_COMPILE_BONE_MEMBER_VALUE_MAP"></a>`CE_COMPILE_BONE_MEMBER_VALUE_MAP` | “&lt;value&gt;: a per-member "v" map names members, and a bone track has one target rather than members. Write the value directly, or move the track onto a group.”<br>Also: “animation "&lt;value&gt;" &lt;value&gt; "&lt;value&gt;" &lt;value&gt;” | Write the bone's value directly or move the member map to a group track. |
7226
+ | <a id="CE_COMPILE_MEMBER_DERIVE_AND_VALUE_MAP"></a>`CE_COMPILE_MEMBER_DERIVE_AND_VALUE_MAP` | “&lt;value&gt;: this key carries both a "derive" model and a per-member "v" map — two answers to one question. The model states the arithmetic and the depths that produced the numbers; the map states the numbers. Pick one.”<br>Also: “{bone / group}”<br>“&lt;value&gt; (t=&lt;value&gt;)”<br>“animation "&lt;value&gt;" &lt;value&gt; "&lt;value&gt;" &lt;value&gt;” | Choose derive arithmetic or a per-member v map. |
7227
+ | <a id="CE_COMPILE_MEMBER_VALUE_NAME_UNKNOWN"></a>`CE_COMPILE_MEMBER_VALUE_NAME_UNKNOWN` | “&lt;value&gt;: the value map names "&lt;value&gt;", which group "&lt;value&gt;" does not declare (its members are: &lt;value&gt;)”<br>Also: “{bone / group}”<br>“&lt;value&gt; (t=&lt;value&gt;)”<br>“animation "&lt;value&gt;" &lt;value&gt; "&lt;value&gt;" &lt;value&gt;” | Use only members declared by the target group in the value map. |
7228
+ | <a id="CE_COMPILE_MEMBER_VALUE_MISSING"></a>`CE_COMPILE_MEMBER_VALUE_MISSING` | “&lt;value&gt;: the value map states no value for member "&lt;value&gt;" (it states: &lt;value&gt;). A member is refused rather than defaulted: an absent value is exactly the thing a map of six is written to make visible, and defaulting it to the identity would key that one bone with a different motion in silence.”<br>Also: “{bone / group}”<br>“&lt;value&gt; (t=&lt;value&gt;)”<br>“animation "&lt;value&gt;" &lt;value&gt; "&lt;value&gt;" &lt;value&gt;”<br>Here the values named in the message include: “nothing”. | Supply a value for every target group member. |
7229
+ | <a id="CE_COMPILE_MEMBER_DERIVE_TARGET_NOT_BONE"></a>`CE_COMPILE_MEMBER_DERIVE_TARGET_NOT_BONE` | “&lt;value&gt;: derive reads member "&lt;value&gt;"'s setup position, and this rig declares no such bone. A model over a group of slots or constraints has no coordinate to be evaluated at — state the values as a "v" map.”<br>Also: “&lt;value&gt; (t=&lt;value&gt;)”<br>“animation "&lt;value&gt;" &lt;value&gt; "&lt;value&gt;" &lt;value&gt;” | Use a v map for slot/constraint groups because they have no bone setup coordinate. |
7230
+ | <a id="CE_COMPILE_MEMBER_DERIVE_PARENTS_DIFFER"></a>`CE_COMPILE_MEMBER_DERIVE_PARENTS_DIFFER` | “&lt;value&gt;: derive measures every member's "&lt;value&gt;" from its parent's origin and "about" says where the axis crosses it, so one space is what makes the members comparable. These members sit under &lt;value&gt; different parents (&lt;value&gt;), and their coordinates are therefore measured from different origins. Split the track by parent, or state the values as a "v" map.”<br>Also: “{bone / group}”<br>“&lt;value&gt; (t=&lt;value&gt;)”<br>“animation "&lt;value&gt;" &lt;value&gt; "&lt;value&gt;" &lt;value&gt;” | Split the derive track by bone parent or state values in a v map. |
7231
+ | <a id="CE_COMPILE_SLOT_TRACK_PROPERTY_UNKNOWN"></a>`CE_COMPILE_SLOT_TRACK_PROPERTY_UNKNOWN` | “animation "&lt;value&gt;" slot "&lt;value&gt;" has no timeline "&lt;value&gt;" (it has: &lt;value&gt;)”<br>Also: “, ” | Use a timeline property supported by slots. |
7232
+ | <a id="CE_COMPILE_DARK_TIMELINE_SETUP_DARK_MISSING"></a>`CE_COMPILE_DARK_TIMELINE_SETUP_DARK_MISSING` | “&lt;value&gt;: slot "&lt;value&gt;" declares no setup "dark", and an "&lt;value&gt;" timeline poses a slot's dark colour — the runtime allocates one only for a slot whose setup pose has it, so applying this animation throws instead of tinting. Give slot "&lt;value&gt;" a `dark` in the rig spec (the colour it holds at rest), or key "[rgba / rgb]" if only the light colour moves”<br>Also: “animation "&lt;value&gt;" slot "&lt;value&gt;" &lt;value&gt;” | State the slot's dark setup colour or use a light-colour timeline. |
7233
+ | <a id="CE_COMPILE_ATTACHMENT_KEY_VALUE_INVALID"></a>`CE_COMPILE_ATTACHMENT_KEY_VALUE_INVALID` | “&lt;value&gt;: attachment key value must be a string or null”<br>Also: “animation "&lt;value&gt;" slot "&lt;value&gt;" &lt;value&gt;” | Use an attachment placeholder string or null. |
7234
+ | <a id="CE_COMPILE_ATTACHMENT_KEY_UNKNOWN"></a>`CE_COMPILE_ATTACHMENT_KEY_UNKNOWN` | “&lt;value&gt;: attachment "&lt;value&gt;" is not in slot "&lt;value&gt;" under any skin (searched: &lt;value&gt;) — [the slot has no attachments at all / the slot has: &lt;value&gt;]”<br>Also: “animation "&lt;value&gt;" slot "&lt;value&gt;" &lt;value&gt;”<br>“, ” | Use an attachment present in the slot under at least one emitted skin. |
7235
+ | <a id="CE_COMPILE_ATTACHMENT_KEY_EASING"></a>`CE_COMPILE_ATTACHMENT_KEY_EASING` | “&lt;value&gt;: attachment keys cannot carry an easing”<br>Also: “animation "&lt;value&gt;" slot "&lt;value&gt;" &lt;value&gt;” | Remove easing from attachment keys. |
7236
+ | <a id="CE_COMPILE_SLOT_KEY_VALUE_SHAPE"></a>`CE_COMPILE_SLOT_KEY_VALUE_SHAPE` | “&lt;value&gt;: &lt;value&gt; key value must be &lt;value&gt;”<br>“[a]”<br>“[lr,lg,lb,dr,dg,db]”<br>“[lr,lg,lb,la,dr,dg,db]”<br>“[r,g,b,a]”<br>“[r,g,b]”<br>Also: “animation "&lt;value&gt;" slot "&lt;value&gt;" &lt;value&gt;” | Supply the colour key array with the shape and channels named in the message. |
7237
+ | <a id="CE_COMPILE_ALPHA_KEY_RANGE_INVALID"></a>`CE_COMPILE_ALPHA_KEY_RANGE_INVALID` | “&lt;value&gt;: key at t=&lt;value&gt; is &lt;value&gt;; an alpha is a number from 0 to 1 — the runtime clamps the posed alpha to that range after interpolating, so a value outside it is one no pose ever holds”<br>Also: “animation "&lt;value&gt;" slot "&lt;value&gt;" &lt;value&gt;” | Keep authored alpha within zero to one. |
7238
+
7239
+
7240
+ #### 5.1.11 Rig shape and setup
7241
+
7242
+ | Code | Fixed message text and alternatives | What to change |
7243
+ | --- | --- | --- |
7244
+ | <a id="CE_RIG_SKIN_OBJECT"></a>`CE_RIG_SKIN_OBJECT` | “&lt;where&gt;: a skin must be an object” | Write the skin as an object in the rig spec. |
7245
+ | <a id="CE_RIG_SKIN_ATTACHMENTS_SHAPE"></a>`CE_RIG_SKIN_ATTACHMENTS_SHAPE` | “&lt;where&gt;: "attachments" is `slotName -&gt; placeholderName -&gt; attachment`, not &lt;JSON.stringify(entry.attachments)&gt;” | Put attachments in a slotName -> placeholderName -> attachment object. |
7246
+ | <a id="CE_RIG_SKIN_LONG_FORM_STRAY_SLOT"></a>`CE_RIG_SKIN_LONG_FORM_STRAY_SLOT` | “&lt;where&gt;: uses the long form (it declares &lt;keys.filter((k) =&gt; known.has(k)).map((k) =&gt; `"${k}"`).join(', ')&gt;) and also has a key "&lt;key&gt;". In that form every key is one of &lt;RIG_SKIN_KEYS.join(', ')&gt; — so "&lt;key&gt;" reads as neither a member list nor a slot, and a slot left outside the block is an attachment that vanishes. Move it inside "attachments".”<br>Here the values named in the message include: “ik”, “path”, “bones”, “slider”, “physics”, “transform”. | Move the slot's attachment table inside the long form's attachments block. |
7247
+ | <a id="CE_RIG_SKIN_MEMBERS_ARRAY"></a>`CE_RIG_SKIN_MEMBERS_ARRAY` | “&lt;where&gt;: "&lt;field&gt;" must be an array of names, not &lt;JSON.stringify(value)&gt;”<br>Here the values named in the message include: “bones”. | Write the named bone or constraint list as an array of names. |
7248
+ | <a id="CE_RIG_SKIN_MEMBER_NAME"></a>`CE_RIG_SKIN_MEMBER_NAME` | “&lt;where&gt;: &lt;field&gt;[&lt;i&gt;] is &lt;JSON.stringify(name)&gt;; a skin lists bones and constraints BY NAME” | Replace the list element with a bone or constraint name string. |
7249
+ | <a id="CE_RIG_SEQUENCE_OBJECT"></a>`CE_RIG_SEQUENCE_OBJECT` | “&lt;where&gt;: &lt;at&gt; is &lt;JSON.stringify(seq) ?? String(seq)&gt;, and a sequence is an object: `{ "count": &lt;frames&gt;, "start"?: &lt;first number&gt;, "digits"?: &lt;zero padding&gt;, "setup"?: &lt;setup frame&gt; }`”<br>Also: “{bone "&lt;value&gt;" / bones[&lt;value&gt;]}”<br>“skin "&lt;value&gt;" slot "&lt;value&gt;" attachment "&lt;value&gt;"”<br>“{stop "&lt;value&gt;" / stops[&lt;value&gt;]}”<br>“&lt;value&gt; "sequence"” | Write sequence as an object stating count and any start, digits and setup values. |
7250
+ | <a id="CE_RIG_SEQUENCE_INTEGER_FIELD"></a>`CE_RIG_SEQUENCE_INTEGER_FIELD` | “&lt;where&gt;: &lt;at&gt;.&lt;field&gt; is &lt;JSON.stringify(value) ?? String(value)&gt;; it is a whole number{ of at least &lt;min&gt; / { of at least 0 / }} — `Sequence.getPath` writes `start + i` into the region name digit for digit, so a fraction names a region like `stem1.5` and a non-number names none”<br>Also: “{bone "&lt;value&gt;" / bones[&lt;value&gt;]}”<br>“skin "&lt;value&gt;" slot "&lt;value&gt;" attachment "&lt;value&gt;"”<br>“{stop "&lt;value&gt;" / stops[&lt;value&gt;]}”<br>“&lt;value&gt; "sequence"”<br>Here the values named in the message include: “setup”, “count”, “digits”. | State whole numbers for sequence fields and respect the printed minimum. |
7251
+ | <a id="CE_RIG_SEQUENCE_COUNT_REQUIRED"></a>`CE_RIG_SEQUENCE_COUNT_REQUIRED` | “&lt;where&gt;: &lt;at&gt; states no "count". The parser reads `getValue(map, "count", 0)` (`SkeletonJson.js:644`), so an omitted count is a series of NO frames: the attachment loads holding no region and draws nothing, without an error. State how many frames the series has.”<br>Also: “{bone "&lt;value&gt;" / bones[&lt;value&gt;]}”<br>“skin "&lt;value&gt;" slot "&lt;value&gt;" attachment "&lt;value&gt;"”<br>“{stop "&lt;value&gt;" / stops[&lt;value&gt;]}”<br>“&lt;value&gt; "sequence"” | State the positive number of frames in sequence.count. |
7252
+ | <a id="CE_RIG_SEQUENCE_SETUP_RANGE"></a>`CE_RIG_SEQUENCE_SETUP_RANGE` | “&lt;where&gt;: &lt;at&gt;.setup is &lt;seq.setup&gt;, and a &lt;count&gt;-frame series has frames 0 to &lt;count - 1&gt;. `Sequence.resolveIndex` clamps an index at or past the end to the LAST frame (measured: `setup: 7` on four frames showed frame 4), so this would show a frame the spec does not name. `setup` is 0-based.”<br>Also: “{bone "&lt;value&gt;" / bones[&lt;value&gt;]}”<br>“skin "&lt;value&gt;" slot "&lt;value&gt;" attachment "&lt;value&gt;"”<br>“{stop "&lt;value&gt;" / stops[&lt;value&gt;]}”<br>“&lt;value&gt; "sequence"” | Set the 0-based setup frame inside 0..count-1. |
7253
+ | <a id="CE_RIG_SEQUENCE_CONFLICTING_FIELD"></a>`CE_RIG_SEQUENCE_CONFLICTING_FIELD` | “&lt;where&gt;: &lt;who&gt; states "&lt;field&gt;" beside "sequence"; &lt;why&gt;. Remove "&lt;field&gt;".”<br>“a generator traces one plate, and which frame of the series it should trace is not something the spec says — author the geometry, which every frame shares”<br>“an image names ONE region and a sequence names `count` of them — the frames are the regions `&lt;path&gt;&lt;number&gt;`, and on the loose route each is the PNG of that name in the images directory”<br>Also: “{bone "&lt;value&gt;" / bones[&lt;value&gt;]}”<br>“skin "&lt;value&gt;" slot "&lt;value&gt;" attachment "&lt;value&gt;"”<br>“{stop "&lt;value&gt;" / stops[&lt;value&gt;]}” | Remove the printed field beside sequence; sequence supplies that value. |
7254
+ | <a id="CE_RIG_SEQUENCE_ATTACHMENT_KIND"></a>`CE_RIG_SEQUENCE_ATTACHMENT_KIND` | “&lt;where&gt;: &lt;who&gt; is a &lt;type&gt; and states a "sequence". A sequence is a numbered series of atlas regions, and only the &lt;SEQUENCE_ATTACHMENT_TYPES.length&gt; kinds that draw a region carry one — &lt;SEQUENCE_ATTACHMENT_TYPES.join(', ')&gt; (`readAttachment` calls `readSequence` in exactly those branches, `SkeletonJson.js:530` and `:561`); on a &lt;type&gt; the parser never reads the key, so the series would be dropped in silence. Remove it, or put it on a region or a mesh.”<br>Also: “{bone "&lt;value&gt;" / bones[&lt;value&gt;]}”<br>“skin "&lt;value&gt;" slot "&lt;value&gt;" attachment "&lt;value&gt;"”<br>“{stop "&lt;value&gt;" / stops[&lt;value&gt;]}”<br>“{absent / &lt;value&gt;}”<br>Here the values named in the message include: “linkedmesh”. | Remove sequence or put it on a region, mesh or linkedmesh attachment. |
7255
+ | <a id="CE_RIG_GENERATOR_KIND"></a>`CE_RIG_GENERATOR_KIND` | “&lt;where&gt;: &lt;who&gt; generator.kind is &lt;stated&gt;; one of &lt;RIG_GENERATOR_KINDS.map((k) =&gt; JSON.stringify(k)).join(', ')&gt; — the kind names the builder, and each builder reads its own keys, so nothing about the mesh can be checked or built without one”<br>Also: “{bone "&lt;value&gt;" / bones[&lt;value&gt;]}”<br>“skin "&lt;value&gt;" slot "&lt;value&gt;" attachment "&lt;value&gt;"”<br>“{stop "&lt;value&gt;" / stops[&lt;value&gt;]}”<br>“{region / &lt;value&gt;}”<br>“{absent / &lt;value&gt;}”<br>Here the values named in the message include: “grid”, “ribbon”, “contour”, “segments”. | State a supported generator.kind and use that builder's fields. |
7256
+ | <a id="CE_RIG_SPEC_OBJECT"></a>`CE_RIG_SPEC_OBJECT` | “&lt;where&gt;: a rig spec must be a JSON object” | Write the rig spec root as a JSON object. |
7257
+ | <a id="CE_RIG_SPEC_VERSION"></a>`CE_RIG_SPEC_VERSION` | “&lt;where&gt;: unknown rig spec version &lt;JSON.stringify(raw.spec)&gt;, expected "&lt;RIG_SPEC_VERSION&gt;"”<br>Here the values named in the message include: “rigc-rig/1”. | Set spec to the version named in the error. |
7258
+ | <a id="CE_RIG_NAME_REQUIRED"></a>`CE_RIG_NAME_REQUIRED` | “&lt;where&gt;: a rig spec needs a "name" — a motion spec names it to pick this rig” | State the rig name used by the motion spec's archetype. |
7259
+ | <a id="CE_RIG_BONES_ARRAY_REQUIRED"></a>`CE_RIG_BONES_ARRAY_REQUIRED` | “&lt;where&gt;: a rig spec needs a non-empty "bones" array” | Declare a non-empty bones array in the rig spec. |
7260
+ | <a id="CE_RIG_SLOTS_ARRAY_REQUIRED"></a>`CE_RIG_SLOTS_ARRAY_REQUIRED` | “&lt;where&gt;: a rig spec needs a "slots" array (it may be empty; its ORDER is the draw order)” | Declare slots as an array; use [] for no slots and keep intended draw order. |
7261
+ | <a id="CE_RIG_SKELETON_AUDIO_TYPE"></a>`CE_RIG_SKELETON_AUDIO_TYPE` | “&lt;where&gt;: "skeleton" states audio &lt;JSON.stringify(header.audio)&gt;; it is a path from the skeleton file to its audio folder, or null for none — a string or null” | Set skeleton.audio to its relative audio folder path or null. |
7262
+ | <a id="CE_RIG_STAGE_EXTENTS_PAIR"></a>`CE_RIG_STAGE_EXTENTS_PAIR` | “&lt;where&gt;: "skeleton" states &lt;absent&gt;: null and a &lt;stated&gt; of &lt;JSON.stringify(noWidth ? header.height : header.width)&gt;. A stage has both extents or neither: write both as null for "this skeleton declares no stage", or give both a number” | Give both stage extents numbers or set both width and height to null. |
7263
+ | <a id="CE_RIG_ABSENT_STAGE_ORIGIN"></a>`CE_RIG_ABSENT_STAGE_ORIGIN` | “&lt;where&gt;: "skeleton" declares no stage (width: null, height: null) and still states &lt;origin.join(' and ')&gt;. &lt;origin.length === 1 ? 'That is an origin' : 'Those are an origin'&gt; for a box that is not there: drop them, or state a width and a height”<br>Also: “{y / &lt;value&gt;}” | Remove stage origins when no stage is declared, or state width and height. |
7264
+ | <a id="CE_RIG_STAGE_BOX_NAMES_REQUIRED"></a>`CE_RIG_STAGE_BOX_NAMES_REQUIRED` | “&lt;where&gt;: skeleton.stageBox states no &lt;missing.map((key) =&gt; `"${key}"`).join(' and ')&gt;. It names the slot the stage box goes in and the attachment name it carries — `{ "slot": "stage", "attachment": "stage" }` — and both are required: rigc writes the box's numbers from the stage and names nothing on its own”<br>Also: “&lt;value&gt; constraint "&lt;value&gt;"” | State both skeleton.stageBox.slot and skeleton.stageBox.attachment. |
7265
+ | <a id="CE_RIG_STAGE_BOX_WITHOUT_STAGE"></a>`CE_RIG_STAGE_BOX_WITHOUT_STAGE` | “&lt;where&gt;: skeleton.stageBox asks for the stage as a bounding box in slot "&lt;box.slot&gt;", and "skeleton" declares no stage (width: null, height: null) — a box around nothing. State a width and a height, or drop stageBox” | Declare stage width and height or remove stageBox. |
7266
+ | <a id="CE_RIG_BONE_NAME_REQUIRED"></a>`CE_RIG_BONE_NAME_REQUIRED` | “&lt;where&gt;: every bone needs a "name"” | Give every bone a non-empty name. |
7267
+ | <a id="CE_RIG_BONE_NAME_DUPLICATE"></a>`CE_RIG_BONE_NAME_DUPLICATE` | “&lt;where&gt;: two bones are called "&lt;bone.name&gt;"; bone names are the join key for slots, meshes and timelines” | Rename a duplicate bone and update references to that bone. |
7268
+ | <a id="CE_RIG_BONE_PARENT_ORDER"></a>`CE_RIG_BONE_PARENT_ORDER` | “&lt;where&gt;: bone "&lt;bone.name&gt;" names parent &lt;JSON.stringify(bone.parent)&gt;, which is not declared before it” | Declare the parent before its child and spell the parent name exactly. |
7269
+ | <a id="CE_RIG_BONE_INHERIT_MODE"></a>`CE_RIG_BONE_INHERIT_MODE` | “&lt;where&gt;: bone "&lt;bone.name&gt;" has inherit &lt;JSON.stringify(bone.inherit)&gt;; &lt;BONE_INHERIT_KNOWN&gt;”<br>“known: &lt;RIG_BONE_INHERIT.join(', ')&gt; — the runtime folds the case of the first letter and of nothing else”<br>Here the values named in the message include: “noScaleOrReflection”, “normal”, “onlyTranslation”, “noRotationOrReflection”. | Use a supported inherit mode with the printed case convention. |
7270
+ | <a id="CE_RIG_BONE_POSITION_SOURCES"></a>`CE_RIG_BONE_POSITION_SOURCES` | “&lt;where&gt;: bone "&lt;bone.name&gt;" takes its position from more than one source (&lt;sources.join(', ')&gt;); name exactly one”<br>Here the values named in the message include: “anchor”, “meshCenter”, “slotWindow”. | Choose exactly one of from.anchor, from.slotWindow or from.meshCenter. |
7271
+ | <a id="CE_RIG_BONE_POSITION_CONFLICT"></a>`CE_RIG_BONE_POSITION_CONFLICT` | “&lt;where&gt;: bone "&lt;bone.name&gt;" declares both a literal x/y and from.&lt;sources[0]&gt;; the two would disagree the first time the art moved”<br>Here the values named in the message include: “anchor”, “meshCenter”, “slotWindow”. | Choose the literal x/y or the manifest position source and remove the other. |
7272
+ | <a id="CE_RIG_BONE_ROTATION_CONFLICT"></a>`CE_RIG_BONE_ROTATION_CONFLICT` | “&lt;where&gt;: bone "&lt;bone.name&gt;" declares both a literal rotation and from.rotation” | Choose literal rotation or from.rotation and remove the other. |
7273
+ | <a id="CE_RIG_BONE_ROTATION_ANCHOR_REQUIRED"></a>`CE_RIG_BONE_ROTATION_ANCHOR_REQUIRED` | “&lt;where&gt;: bone "&lt;bone.name&gt;" wants its rotation from an anchor but names no from.anchor” | Name from.anchor when from.rotation takes its rotation from an anchor. |
7274
+ | <a id="CE_RIG_SLOT_NAME_REQUIRED"></a>`CE_RIG_SLOT_NAME_REQUIRED` | “&lt;where&gt;: every slot needs a "name"” | Give every slot a non-empty name. |
7275
+ | <a id="CE_RIG_SLOT_NAME_DUPLICATE"></a>`CE_RIG_SLOT_NAME_DUPLICATE` | “&lt;where&gt;: two slots are called "&lt;slot.name&gt;"” | Rename a duplicate slot and update references to that slot. |
7276
+ | <a id="CE_RIG_SLOT_BONE_UNKNOWN"></a>`CE_RIG_SLOT_BONE_UNKNOWN` | “&lt;where&gt;: slot "&lt;slot.name&gt;" names bone &lt;JSON.stringify(slot.bone)&gt;, which this rig does not declare” | Name a declared bone in slot.bone. |
7277
+ | <a id="CE_RIG_SLOT_BLEND_MODE"></a>`CE_RIG_SLOT_BLEND_MODE` | “&lt;where&gt;: slot "&lt;slot.name&gt;" has blend &lt;JSON.stringify(slot.blend)&gt;; known: &lt;RIG_SLOT_BLEND.join(', ')&gt; (only the first letter's case is free — the parser's enumValue uppercases that one character and nothing else, and an unresolved name becomes undefined without an error)”<br>Here the values named in the message include: “screen”, “normal”, “additive”, “multiply”. | Use a printed blend mode; only its first letter's case is free. |
7278
+ | <a id="CE_RIG_DEFORM_FOLD_EXEMPTIONS_SHAPE"></a>`CE_RIG_DEFORM_FOLD_EXEMPTIONS_SHAPE` | “&lt;where&gt;: invariants.deformMayFold is &lt;JSON.stringify(mayFold)&gt;, expected an array of { "slot": …, "why": … }” | Write invariants.deformMayFold as an array of {slot, why} entries. |
7279
+ | <a id="CE_RIG_DEFORM_FOLD_SLOT_REQUIRED"></a>`CE_RIG_DEFORM_FOLD_SLOT_REQUIRED` | “&lt;where&gt;: every invariants.deformMayFold entry needs a "slot"” | Name the exempted slot in each deformMayFold entry. |
7280
+ | <a id="CE_RIG_DEFORM_FOLD_SLOT_UNKNOWN"></a>`CE_RIG_DEFORM_FOLD_SLOT_UNKNOWN` | “&lt;where&gt;: invariants.deformMayFold exempts slot "&lt;entry.slot&gt;", which this rig does not declare — a name that resolves to nothing exempts nothing, and reads like the exemption worked” | Name an existing slot in deformMayFold or remove the exemption. |
7281
+ | <a id="CE_RIG_DEFORM_FOLD_SLOT_DUPLICATE"></a>`CE_RIG_DEFORM_FOLD_SLOT_DUPLICATE` | “&lt;where&gt;: invariants.deformMayFold names slot "&lt;entry.slot&gt;" twice” | Keep one deformMayFold entry for each slot. |
7282
+ | <a id="CE_RIG_DEFORM_FOLD_REASON_REQUIRED"></a>`CE_RIG_DEFORM_FOLD_REASON_REQUIRED` | “&lt;where&gt;: invariants.deformMayFold entry for slot "&lt;entry.slot&gt;" needs a "why" — this field switches A39_DEFORM_KEEPS_TRIANGLE_WINDING off for that slot, and an exemption nobody can date or justify is how a defect ships as a decision” | Record a non-blank why explaining the intentional fold exemption. |
7283
+ | <a id="CE_RIG_CONSTRAINT_NAME_REQUIRED"></a>`CE_RIG_CONSTRAINT_NAME_REQUIRED` | “&lt;where&gt;: every constraint needs a "name"” | Give every constraint a non-empty name. |
7284
+
7285
+
7286
+ #### 5.1.12 Rig constraints, invariants and skins
7287
+
7288
+ | Code | Fixed message text and alternatives | What to change |
7289
+ | --- | --- | --- |
7290
+ | <a id="CE_RIG_CONSTRAINT_NAME_DUPLICATE"></a>`CE_RIG_CONSTRAINT_NAME_DUPLICATE` | “&lt;where&gt;: two &lt;declared.type&gt; constraints are called "&lt;declared.name&gt;" — a constraint resolves by name AND type (`SkeletonData.findConstraint`), so names are unique PER KIND: an ik and a transform constraint may share one, two of a kind may not” | Use a unique name within each constraint kind and update references. |
7291
+ | <a id="CE_RIG_IK_BONES_SHAPE"></a>`CE_RIG_IK_BONES_SHAPE` | “&lt;where&gt;: &lt;fault&gt;”<br>“ik constraint "&lt;name&gt;" names &lt;bones.length&gt; bones (&lt;quoted(bones)&gt;); the solver applies one or two, so a constraint over &lt;bones.length&gt; moves nothing — name one bone, or two where the second is the first's child”<br>“ik constraint "&lt;name&gt;": "&lt;second&gt;" is not a child of "&lt;first&gt;" (&lt;why&gt;), so the two-bone solve is not of the chain drawn — name "&lt;second&gt;"'s own parent as the first bone, or make "&lt;second&gt;" a child of "&lt;first&gt;"”<br>“{&lt;quoted(secondAncestors.slice(0, at))&gt; &lt;at === 1 ? 'stands' : 'stand'&gt; between / {"&lt;second&gt;" has no parent / "&lt;first&gt;" is not above it; its parent is "&lt;secondAncestors[0]&gt;"}}”<br>Also: “&lt;value&gt;: skin "&lt;value&gt;"” | Use one bone, or two with the second bone parented directly to the first. |
7292
+ | <a id="CE_RIG_CONSUMER_MIX_EXEMPTIONS_SHAPE"></a>`CE_RIG_CONSUMER_MIX_EXEMPTIONS_SHAPE` | “&lt;where&gt;: invariants.consumerDrivenMix is &lt;JSON.stringify(consumerDriven)&gt;, expected &lt;shape&gt;”<br>“an array of { "constraint": …, "type": "ik" \| "transform", "why": … }”<br>Also: “{ "why": "&lt;why this idle deforms meshes on purpose&gt;" }”<br>“an array of { "name": …, "through": [&lt;bone&gt;, &lt;bone&gt;], "bones": [&lt;bone&gt;, …], "tolerance": &lt;degrees&gt; }” | Write consumerDrivenMix as the printed array of {constraint, type, why} entries. |
7293
+ | <a id="CE_RIG_CONSUMER_MIX_CONSTRAINT_REQUIRED"></a>`CE_RIG_CONSUMER_MIX_CONSTRAINT_REQUIRED` | “&lt;where&gt;: every invariants.consumerDrivenMix entry needs a "constraint" — &lt;shape&gt;”<br>“an array of { "constraint": …, "type": "ik" \| "transform", "why": … }”<br>Also: “{ "why": "&lt;why this idle deforms meshes on purpose&gt;" }”<br>“an array of { "name": …, "through": [&lt;bone&gt;, &lt;bone&gt;], "bones": [&lt;bone&gt;, …], "tolerance": &lt;degrees&gt; }” | State the constraint name in each consumerDrivenMix entry. |
7294
+ | <a id="CE_RIG_CONSUMER_MIX_KIND"></a>`CE_RIG_CONSUMER_MIX_KIND` | “&lt;where&gt;: invariants.consumerDrivenMix entry for "&lt;entry.constraint&gt;" has type &lt;JSON.stringify(entry.type)&gt;; only "ik" and "transform" read this declaration (A47_IK_CONSTRAINT_NOT_MUTED_THROUGHOUT, A48_TRANSFORM_CONSTRAINT_NOT_MUTED_THROUGHOUT). A path, physics or slider constraint resting muted is A36, A23 or A37, which read no declaration, so the entry would exempt nothing{ — the rig declares "&lt;entry.constraint&gt;" as &lt;declaredAs.map((t) =&gt; `${t === 'ik' ? 'an' : 'a'} ${t}`).join(' and ')&gt; constraint / }” | Use ik or transform for consumerDrivenMix; other kinds do not read this exemption. |
7295
+ | <a id="CE_RIG_CONSUMER_MIX_CONSTRAINT_UNKNOWN"></a>`CE_RIG_CONSUMER_MIX_CONSTRAINT_UNKNOWN` | “&lt;where&gt;: invariants.consumerDrivenMix names &lt;key&gt;, which this rig does not declare{ — "&lt;entry.constraint&gt;" is declared as &lt;declaredAs.map((t) =&gt; `${t === 'ik' ? 'an' : 'a'} ${t}`).join(' and ')&gt; constraint, and a constraint resolves by name AND type / }. A name that resolves to nothing exempts nothing, and reads like the exemption worked”<br>Also: “&lt;value&gt; constraint "&lt;value&gt;"” | Match both the declared constraint name and its kind, or remove the exemption. |
7296
+ | <a id="CE_RIG_CONSUMER_MIX_CONSTRAINT_DUPLICATE"></a>`CE_RIG_CONSUMER_MIX_CONSTRAINT_DUPLICATE` | “&lt;where&gt;: invariants.consumerDrivenMix names &lt;key&gt; twice”<br>Also: “&lt;value&gt; constraint "&lt;value&gt;"” | Keep one consumerDrivenMix entry per constraint name and kind. |
7297
+ | <a id="CE_RIG_CONSUMER_MIX_REASON_REQUIRED"></a>`CE_RIG_CONSUMER_MIX_REASON_REQUIRED` | “&lt;where&gt;: invariants.consumerDrivenMix entry for &lt;key&gt; needs a "why" — this field switches &lt;entry.type === 'ik' ? 'A47_IK_CONSTRAINT_NOT_MUTED_THROUGHOUT' : 'A48_TRANSFORM_CONSTRAINT_NOT_MUTED_THROUGHOUT'&gt; off for that constraint, and an exemption nobody can date or justify is how a defect ships as a decision”<br>Also: “&lt;value&gt; constraint "&lt;value&gt;"” | Record a non-blank why explaining the consumer-driven mix exemption. |
7298
+ | <a id="CE_RIG_IDLE_MESH_EXEMPTION_SHAPE"></a>`CE_RIG_IDLE_MESH_EXEMPTION_SHAPE` | “&lt;where&gt;: invariants.idleDrivesMeshes is &lt;JSON.stringify(idleDrives)&gt;, expected &lt;shape&gt;”<br>“{ "why": "&lt;why this idle deforms meshes on purpose&gt;" }”<br>Also: “an array of { "constraint": …, "type": "ik" \| "transform", "why": … }”<br>“an array of { "name": …, "through": [&lt;bone&gt;, &lt;bone&gt;], "bones": [&lt;bone&gt;, …], "tolerance": &lt;degrees&gt; }” | Write idleDrivesMeshes in the printed {why} object shape. |
7299
+ | <a id="CE_RIG_IDLE_MESH_REASON_REQUIRED"></a>`CE_RIG_IDLE_MESH_REASON_REQUIRED` | “&lt;where&gt;: invariants.idleDrivesMeshes needs a "why" (a non-blank string), got &lt;idleDrives.why === undefined ? 'none' : JSON.stringify(idleDrives.why)&gt; — expected &lt;shape&gt;. This field switches A15_IDLE_NO_MESH_BONE_KEYS off, and an exemption nobody can date or justify is how a defect ships as a decision”<br>“{ "why": "&lt;why this idle deforms meshes on purpose&gt;" }”<br>Also: “an array of { "constraint": …, "type": "ik" \| "transform", "why": … }”<br>“an array of { "name": …, "through": [&lt;bone&gt;, &lt;bone&gt;], "bones": [&lt;bone&gt;, …], "tolerance": &lt;degrees&gt; }” | Record a non-blank why explaining why idle intentionally drives mesh bones. |
7300
+ | <a id="CE_RIG_AXES_SHAPE"></a>`CE_RIG_AXES_SHAPE` | “&lt;where&gt;: invariants.axes is &lt;JSON.stringify(axes)&gt;, expected &lt;shape&gt;”<br>“an array of { "name": …, "through": [&lt;bone&gt;, &lt;bone&gt;], "bones": [&lt;bone&gt;, …], "tolerance": &lt;degrees&gt; }”<br>Also: “{ "why": "&lt;why this idle deforms meshes on purpose&gt;" }”<br>“an array of { "constraint": …, "type": "ik" \| "transform", "why": … }” | Write invariants.axes as the printed array of axis declarations. |
7301
+ | <a id="CE_RIG_AXIS_NAME_REQUIRED"></a>`CE_RIG_AXIS_NAME_REQUIRED` | “&lt;where&gt;: &lt;field&gt; needs a "name" — &lt;shape&gt;”<br>“an array of { "name": …, "through": [&lt;bone&gt;, &lt;bone&gt;], "bones": [&lt;bone&gt;, …], "tolerance": &lt;degrees&gt; }”<br>Also: “invariants.axes[&lt;value&gt;]”<br>“{ "why": "&lt;why this idle deforms meshes on purpose&gt;" }”<br>“an array of { "constraint": …, "type": "ik" \| "transform", "why": … }” | Give each invariant axis a non-empty name. |
7302
+ | <a id="CE_RIG_AXIS_NAME_DUPLICATE"></a>`CE_RIG_AXIS_NAME_DUPLICATE` | “&lt;where&gt;: &lt;field&gt;: invariants.axes names "&lt;entry.name&gt;" twice — a failure names its entry, and two entries of one name could not be told apart”<br>Also: “invariants.axes[&lt;value&gt;]” | Use a unique name for each invariant axis. |
7303
+ | <a id="CE_RIG_AXIS_THROUGH_PAIR"></a>`CE_RIG_AXIS_THROUGH_PAIR` | “&lt;where&gt;: &lt;axis&gt;: "through" is &lt;JSON.stringify(through)&gt;, expected two bone names — the line is drawn through their setup-pose world origins”<br>Also: “invariants.axes[&lt;value&gt;]” | State two bone names in the axis through array. |
7304
+ | <a id="CE_RIG_AXIS_THROUGH_BONE_UNKNOWN"></a>`CE_RIG_AXIS_THROUGH_BONE_UNKNOWN` | “&lt;where&gt;: &lt;axis&gt;: through[&lt;k&gt;] names bone "&lt;bone&gt;", which this rig does not declare — a line through nothing holds nothing”<br>Also: “invariants.axes[&lt;value&gt;]” | Name a declared bone in each through entry. |
7305
+ | <a id="CE_RIG_AXIS_THROUGH_BONE_DUPLICATE"></a>`CE_RIG_AXIS_THROUGH_BONE_DUPLICATE` | “&lt;where&gt;: &lt;axis&gt;: "through" names bone "&lt;through[0]&gt;" twice — one bone's origin is a point, and a point draws no line”<br>Also: “invariants.axes[&lt;value&gt;]” | Choose two different bones whose origins define the axis line. |
7306
+ | <a id="CE_RIG_AXIS_BONES_ARRAY"></a>`CE_RIG_AXIS_BONES_ARRAY` | “&lt;where&gt;: &lt;axis&gt;: "bones" is &lt;JSON.stringify(bones)&gt;, expected a non-empty array of bone names — the bones held to the line”<br>Also: “invariants.axes[&lt;value&gt;]” | State a non-empty array of bones held to the axis. |
7307
+ | <a id="CE_RIG_AXIS_HELD_BONE_UNKNOWN"></a>`CE_RIG_AXIS_HELD_BONE_UNKNOWN` | “&lt;where&gt;: &lt;axis&gt;: bones[&lt;k&gt;] names bone "&lt;bone&gt;", which this rig does not declare — a name that resolves to nothing is held to nothing, and reads like it was”<br>Also: “invariants.axes[&lt;value&gt;]” | Name a declared bone in the axis bones array. |
7308
+ | <a id="CE_RIG_AXIS_HELD_BONE_DUPLICATE"></a>`CE_RIG_AXIS_HELD_BONE_DUPLICATE` | “&lt;where&gt;: &lt;axis&gt;: "bones" names bone "&lt;bone&gt;" twice”<br>Also: “invariants.axes[&lt;value&gt;]” | List each bone only once in the axis bones array. |
7309
+ | <a id="CE_RIG_AXIS_TOLERANCE_RANGE"></a>`CE_RIG_AXIS_TOLERANCE_RANGE` | “&lt;where&gt;: &lt;axis&gt;: "tolerance" is &lt;tolerance === undefined ? 'absent' : JSON.stringify(tolerance)&gt;; it must be a number of degrees above 0 and below 90, and there is no default — two lines meet at 0° to 90°, so 90 or more admits every orientation and can never fail, and 0 refuses a bone rotated exactly onto the line whenever the posed arithmetic rounds”<br>Also: “invariants.axes[&lt;value&gt;]” | State tolerance in degrees strictly above 0 and below 90. |
7310
+ | <a id="CE_RIG_SKINS_TABLE"></a>`CE_RIG_SKINS_TABLE` | “&lt;where&gt;: "skins" is an object keyed by skin name” | Write skins as an object keyed by skin name. |
7311
+ | <a id="CE_RIG_SLOT_SKIN_KEY_COLLISION"></a>`CE_RIG_SLOT_SKIN_KEY_COLLISION` | “&lt;where&gt;: a slot is called "&lt;collision&gt;", which is one of the keys that tell a skin's long form (`{ "attachments": {…}, "bones": [...] }`) from its short one (`slotName -&gt; placeholder -&gt; attachment`): &lt;RIG_SKIN_KEYS.join(', ')&gt;. Rename the slot.”<br>Here the values named in the message include: “ik”, “path”, “slider”, “physics”, “transform”. | Rename the slot that collides with a reserved long-form skin key. |
7312
+ | <a id="CE_RIG_SKIN_BONE_UNKNOWN"></a>`CE_RIG_SKIN_BONE_UNKNOWN` | “&lt;at&gt; activates bone "&lt;bone&gt;", which this rig does not declare”<br>Also: “&lt;value&gt;: skin "&lt;value&gt;"” | Name an existing bone in the skin's bones list. |
7313
+ | <a id="CE_RIG_SKIN_BONE_NOT_REQUIRED"></a>`CE_RIG_SKIN_BONE_NOT_REQUIRED` | “&lt;at&gt; activates bone "&lt;bone&gt;", but that bone does not declare `"skin": true`. Skeleton.updateCache starts a bone active unless it is skinRequired, so this list changes nothing — the bone poses under every skin.”<br>Also: “&lt;value&gt;: skin "&lt;value&gt;"” | Declare skin:true on that bone if skin activation is intended, or remove the redundant list entry. |
7314
+ | <a id="CE_RIG_SKIN_CONSTRAINT_UNKNOWN"></a>`CE_RIG_SKIN_CONSTRAINT_UNKNOWN` | “&lt;at&gt; activates &lt;type&gt; constraint "&lt;name&gt;", which this rig does not declare”<br>Also: “&lt;value&gt;: skin "&lt;value&gt;"” | Name an existing constraint in the skin list for its kind. |
7315
+ | <a id="CE_RIG_SKIN_CONSTRAINT_KIND"></a>`CE_RIG_SKIN_CONSTRAINT_KIND` | “&lt;at&gt; lists "&lt;name&gt;" under "&lt;type&gt;", but the rig declares it as a "&lt;kinds.join('", "')&gt;" constraint — a skin looks its constraints up by name AND type, so this one is a miss and the loader throws”<br>Also: “&lt;value&gt;: skin "&lt;value&gt;"” | Move the constraint name to the skin list matching its declared kind. |
7316
+ | <a id="CE_RIG_SKIN_CONSTRAINT_NOT_REQUIRED"></a>`CE_RIG_SKIN_CONSTRAINT_NOT_REQUIRED` | “&lt;at&gt; activates &lt;type&gt; constraint "&lt;name&gt;", but that constraint does not declare `"skin": true`. A constraint is active unless it is skinRequired, so this list changes nothing.”<br>Also: “&lt;value&gt;: skin "&lt;value&gt;"” | Declare skin:true on that constraint if activation is intended, or remove the redundant list entry. |
7317
+ | <a id="CE_RIG_BONE_SKIN_NEVER_ACTIVE"></a>`CE_RIG_BONE_SKIN_NEVER_ACTIVE` | “&lt;where&gt;: bone "&lt;bone.name&gt;" declares `"skin": true` but no skin activates it, so it is never active — list it in the skin it belongs to, or drop the flag” | List the skin-required bone in a skin that activates it, or remove skin:true. |
7318
+ | <a id="CE_RIG_CONSTRAINT_SKIN_NEVER_ACTIVE"></a>`CE_RIG_CONSTRAINT_SKIN_NEVER_ACTIVE` | “&lt;where&gt;: &lt;type&gt; constraint "&lt;name&gt;" declares `"skin": true` but no skin activates it, so it never runs — list it in that skin's "&lt;type&gt;" array, or drop the flag” | List the skin-required constraint in that skin's matching kind array, or remove skin:true. |
7319
+ | <a id="CE_RIG_EVENTS_TABLE"></a>`CE_RIG_EVENTS_TABLE` | “&lt;where&gt;: "events" is an object keyed by event name (`{ "footstep": {} }`), not an array — the format's own shape” | Write events as an object keyed by event name, with {} for an event without defaults. |
7320
+ | <a id="CE_RIG_EVENT_NAME_EMPTY"></a>`CE_RIG_EVENT_NAME_EMPTY` | “&lt;where&gt;: an event has an empty name” | Give the event a non-empty name. |
7321
+ | <a id="CE_RIG_EVENT_DEFAULTS_OBJECT"></a>`CE_RIG_EVENT_DEFAULTS_OBJECT` | “&lt;where&gt;: event "&lt;name&gt;" must be an object of payload defaults (use {} for none)” | Write the event payload defaults as an object, using {} for none. |
7322
+ | <a id="CE_RIG_EVENT_NUMBER_FINITE"></a>`CE_RIG_EVENT_NUMBER_FINITE` | “&lt;where&gt;: event "&lt;name&gt;" has &lt;field&gt; &lt;JSON.stringify(v)&gt;, which is not a finite number”<br>Also: “invariants.axes[&lt;value&gt;]” | Use finite numeric event defaults for the printed field. |
7323
+ | <a id="CE_RIG_EVENT_INT_WHOLE"></a>`CE_RIG_EVENT_INT_WHOLE` | “&lt;where&gt;: event "&lt;name&gt;" has int &lt;JSON.stringify(def.int)&gt;; the payload is an integer” | Use a whole number for the event int payload default. |
7324
+ | <a id="CE_RIG_EVENT_STRING_TYPE"></a>`CE_RIG_EVENT_STRING_TYPE` | “&lt;where&gt;: event "&lt;name&gt;" has &lt;field&gt; &lt;JSON.stringify(def[field])&gt;, which is not a string”<br>Also: “invariants.axes[&lt;value&gt;]” | Use a string for the printed event payload field. |
7325
+ | <a id="CE_RIG_EVENT_AUDIO_REQUIRED"></a>`CE_RIG_EVENT_AUDIO_REQUIRED` | “&lt;where&gt;: event "&lt;name&gt;" declares &lt;field&gt; but no "audio"; the parser reads &lt;field&gt; only when an audio path is set, so it would be dropped in silence”<br>Also: “invariants.axes[&lt;value&gt;]” | State the event audio path before audio-only fields, or remove those fields. |
7326
+
7327
+
7328
+ #### 5.1.13 Stop declarations
7329
+
7330
+ | Code | Fixed message text and alternatives | What to change |
7331
+ | --- | --- | --- |
7332
+ | <a id="CE_STOP_DECLARATIONS_ARRAY"></a>`CE_STOP_DECLARATIONS_ARRAY` | “&lt;where&gt;: "stops" is &lt;JSON.stringify(declared)&gt;; it is an array of { "chain", "links", "against", "at", "inward", "outward", "lower"? }” | Write stops as an array of declarations with the fields printed in the error. |
7333
+ | <a id="CE_STOP_DECLARATION_OBJECT"></a>`CE_STOP_DECLARATION_OBJECT` | “&lt;where&gt;: stops[&lt;i&gt;] is &lt;JSON.stringify(entry)&gt;; a stop is an object” | Write each stop declaration as an object. |
7334
+ | <a id="CE_STOP_CHAIN_NAME_REQUIRED"></a>`CE_STOP_CHAIN_NAME_REQUIRED` | “&lt;where&gt;: stops[&lt;i&gt;] needs a "chain" — the name its point, frame and aim are called after ("&lt;chain&gt;_touch", "&lt;chain&gt;_stop", "&lt;chain&gt;_stop_aim")” | State the stop chain name used for its generated bones and constraints. |
7335
+ | <a id="CE_STOP_LINKS_ARRAY"></a>`CE_STOP_LINKS_ARRAY` | “&lt;who&gt; states "links" &lt;JSON.stringify(links) ?? 'absent'&gt;; it is the chain's swinging links, root first — a non-empty array of bone names”<br>Also: “&lt;value&gt;: stop "&lt;value&gt;"” | List swinging bone names root first in a non-empty links array. |
7336
+ | <a id="CE_STOP_LINK_UNKNOWN"></a>`CE_STOP_LINK_UNKNOWN` | “&lt;who&gt;: links[&lt;k&gt;] names bone "&lt;link&gt;", which this rig does not declare”<br>Also: “&lt;value&gt;: stop "&lt;value&gt;"” | Name an existing bone in links. |
7337
+ | <a id="CE_STOP_LINK_ALREADY_STOPPED"></a>`CE_STOP_LINK_ALREADY_STOPPED` | “&lt;who&gt;: links[&lt;k&gt;] "&lt;link&gt;" is already stopped by stop "&lt;other&gt;" — one drawn link "&lt;link&gt;_d" and one clamp "&lt;link&gt;_clamp" per link, so a link is stopped once”<br>Also: “&lt;value&gt;: stop "&lt;value&gt;"” | Assign each swinging link to only one stop. |
7338
+ | <a id="CE_STOP_LINK_MANIFEST_POSITION"></a>`CE_STOP_LINK_MANIFEST_POSITION` | “&lt;who&gt;: links[&lt;k&gt;] "&lt;link&gt;" takes its place from the manifest ("from"), and a stop copies the link's stated x, y and rotation onto its drawn link — state them”<br>Also: “&lt;value&gt;: stop "&lt;value&gt;"” | State the swinging link's x, y and rotation in the rig spec instead of from. |
7339
+ | <a id="CE_STOP_LINK_ROOT"></a>`CE_STOP_LINK_ROOT` | “&lt;who&gt;: links[&lt;k&gt;] "&lt;link&gt;" is the skeleton's root, and a stop hangs its frame and its drawn link where the link hangs — a link has a parent”<br>Also: “&lt;value&gt;: stop "&lt;value&gt;"” | Use a swinging link with a parent; the skeleton root cannot be stopped. |
7340
+ | <a id="CE_STOP_AGAINST_REQUIRED"></a>`CE_STOP_AGAINST_REQUIRED` | “&lt;who&gt; needs "against" — the bone the point rides on, the leg the chain is held off”<br>Also: “&lt;value&gt;: stop "&lt;value&gt;"” | State the against bone carrying the contact point. |
7341
+ | <a id="CE_STOP_AGAINST_UNKNOWN"></a>`CE_STOP_AGAINST_UNKNOWN` | “&lt;who&gt;: "against" names bone "&lt;against&gt;", which this rig does not declare”<br>Also: “&lt;value&gt;: stop "&lt;value&gt;"” | Name an existing against bone. |
7342
+ | <a id="CE_STOP_AT_REQUIRED"></a>`CE_STOP_AT_REQUIRED` | “&lt;who&gt; states no "at" — the point on "&lt;against&gt;" the frame aims at, [x, y] in "&lt;against&gt;"'s local space; the compiler places no point of its own”<br>Also: “&lt;value&gt;: stop "&lt;value&gt;"” | State at as the contact point [x, y] in the against bone's local space. |
7343
+ | <a id="CE_STOP_AT_PAIR"></a>`CE_STOP_AT_PAIR` | “&lt;who&gt; states "at" &lt;JSON.stringify(at)&gt;; it is [x, y], two numbers in "&lt;against&gt;"'s local space”<br>Also: “&lt;value&gt;: stop "&lt;value&gt;"” | Write at as two numbers in the against bone's local space. |
7344
+ | <a id="CE_STOP_RANGE_END_REQUIRED"></a>`CE_STOP_RANGE_END_REQUIRED` | “&lt;who&gt; states no "&lt;field&gt;&lt;end&gt;" — degrees from the link's rest angle, counted positive away from "&lt;against&gt;"; the range is [inward, outward], and the compiler states neither end for you”<br>Also: “&lt;value&gt;: stop "&lt;value&gt;"” | State both inward and outward limits for the printed range. |
7345
+ | <a id="CE_STOP_RANGE_REVERSED"></a>`CE_STOP_RANGE_REVERSED` | “&lt;who&gt;: "&lt;field&gt;inward" &lt;out.inward&gt; is greater than "&lt;field&gt;outward" &lt;out.outward&gt; — the range is [inward, outward] in degrees counted positive away from "&lt;against&gt;", and this one holds no angle”<br>Also: “&lt;value&gt;: stop "&lt;value&gt;"” | Keep inward less than or equal to outward in the printed range. |
7346
+ | <a id="CE_STOP_LOWER_REQUIRED"></a>`CE_STOP_LOWER_REQUIRED` | “&lt;who&gt; states no "lower" — the range [inward, outward] each link below the first may turn through off its own rest bend; the chain has &lt;links.length - 1&gt; of them”<br>Also: “&lt;value&gt;: stop "&lt;value&gt;"” | State the lower inward/outward range for links below the first. |
7347
+ | <a id="CE_STOP_LOWER_WITH_ONE_LINK"></a>`CE_STOP_LOWER_WITH_ONE_LINK` | “&lt;who&gt; states "lower" and its chain has one link — there is no link below the first for it to hold”<br>Also: “&lt;value&gt;: stop "&lt;value&gt;"” | Remove lower when the chain contains one link. |
7348
+ | <a id="CE_STOP_GENERATED_BONE_DECLARED"></a>`CE_STOP_GENERATED_BONE_DECLARED` | “&lt;stop.who&gt; generates bone "&lt;name&gt;", which this rig already declares — rename the bone, or the stop's "chain"” | Rename the colliding declared bone or stop chain. |
7349
+ | <a id="CE_STOP_GENERATED_BONE_COLLISION"></a>`CE_STOP_GENERATED_BONE_COLLISION` | “&lt;stop.who&gt; generates bone "&lt;name&gt;", which stop "&lt;by&gt;" generates too — rename one "chain"” | Give the stops distinct chain names so generated bones differ. |
7350
+ | <a id="CE_STOP_GENERATED_CONSTRAINT_DECLARED"></a>`CE_STOP_GENERATED_CONSTRAINT_DECLARED` | “&lt;stop.who&gt; generates &lt;type&gt; constraint "&lt;name&gt;", which this rig already declares — rename the constraint, or the stop's "chain"”<br>Here the values named in the message include: “ik”, “transform”. | Rename the colliding declared constraint or stop chain. |
7351
+ | <a id="CE_STOP_GENERATED_CONSTRAINT_COLLISION"></a>`CE_STOP_GENERATED_CONSTRAINT_COLLISION` | “&lt;stop.who&gt; generates &lt;type&gt; constraint "&lt;name&gt;", which stop "&lt;by&gt;" generates too — rename one "chain"”<br>Here the values named in the message include: “ik”, “transform”. | Give the stops distinct chain names so generated constraints differ. |
7352
+ | <a id="CE_STOP_LINK_UNDRIVEN"></a>`CE_STOP_LINK_UNDRIVEN` | “&lt;stop.who&gt;: links[&lt;k&gt;] "&lt;link&gt;" is written by no constraint of this rig spec — a stop holds a link something swings (a physics, ik, transform or path constraint in "constraints"), and its copy and clamp run right after that. A physics constraint in the motion spec's table is emitted after every rig constraint, past the clamp; declare it here” | Declare the swinging physics, ik, transform or path constraint in the rig spec's constraints before its stop clamp. |
7353
+ | <a id="CE_STOP_LINK_PARENT_CHAIN"></a>`CE_STOP_LINK_PARENT_CHAIN` | “&lt;stop.who&gt;: links[&lt;k&gt;] "&lt;links[k]&gt;" does not hang below "&lt;names.drawn[k - 1]&gt;", the drawn link of links[&lt;k - 1&gt;] — a chain's next link hangs from the drawn link above it, so the clamp that holds that one carries this one; parent it there” | Parent each lower link under the preceding generated drawn link. |
7354
+ | <a id="CE_STOP_AGAINST_MOVES_WITH_STOP"></a>`CE_STOP_AGAINST_MOVES_WITH_STOP` | “&lt;stop.who&gt;: "against" "&lt;stop.against&gt;" hangs below "&lt;under&gt;", which the stop moves — the point would swing with the chain it holds off; name the leg” | Name an against bone outside the subtree moved by the stop. |
7355
+ | <a id="CE_STOP_LOCAL_BOUND_RANGE"></a>`CE_STOP_LOCAL_BOUND_RANGE` | “&lt;stop.who&gt;: "&lt;field&gt;&lt;end&gt;" &lt;range[end]&gt; puts &lt;what&gt;'s bound at &lt;value&gt;°, past ±&lt;BOUND&gt;° — the clamp reads a local rotation in (-180, 180], so a bound past it is never reached and the range it states is not the one that holds”<br>Here the values named in the message include: “inward”, “outward”. | Adjust the printed limits so the local clamp bounds stay within its supported angular range. |
7356
+ | <a id="CE_STOP_DEPENDENCY_ORDER"></a>`CE_STOP_DEPENDENCY_ORDER` | “&lt;who&gt;: "&lt;tip&gt;" hangs below "&lt;name&gt;", which a later stop generates — declare that stop first, so its angles are known when this one is read”<br>Also: “&lt;value&gt;: stop "&lt;value&gt;"” | Declare the stop generating the parent before the stop depending on it. |
7357
+ | <a id="CE_STOP_ANCESTOR_MANIFEST_POSITION"></a>`CE_STOP_ANCESTOR_MANIFEST_POSITION` | “&lt;who&gt;: "&lt;name&gt;" takes its place from the manifest ("from"), and a stop's angles are read off the setup pose this rig spec states — state its x, y and rotation”<br>Also: “&lt;value&gt;: stop "&lt;value&gt;"” | State x, y and rotation for the named setup-pose ancestor instead of from. |
7358
+ | <a id="CE_STOP_FRAME_PARENT_TRANSFORM"></a>`CE_STOP_FRAME_PARENT_TRANSFORM` | “&lt;who&gt;: "&lt;parent&gt;", where the frame hangs, is scaled unevenly, sheared or reflected at the setup pose — the frame's angles add to its parent's only through a rotation and an even scale, and inward is a turn's sense”<br>Also: “&lt;value&gt;: stop "&lt;value&gt;"” | Use a frame parent with rotation and even positive scale, without shear or reflection. |
7359
+ | <a id="CE_STOP_LOWER_PARENT_TRANSFORM"></a>`CE_STOP_LOWER_PARENT_TRANSFORM` | “&lt;who&gt;: "&lt;at&gt;", between links[&lt;k&gt;] "&lt;links[k]&gt;" and the drawn link above it, is scaled unevenly, sheared, reflected or inherits other than normally — a lower clamp reads the link's turn in its parent, and inward is a turn's sense”<br>Also: “&lt;value&gt;: stop "&lt;value&gt;"” | Use normal inheritance and even positive scale without shear or reflection between stopped links. |
7360
+ | <a id="CE_STOP_POINT_AT_ROOT"></a>`CE_STOP_POINT_AT_ROOT` | “&lt;who&gt;: "at" [&lt;stop.at.join(', ')&gt;] on "&lt;stop.against&gt;" sits on the root of "&lt;links[0]&gt;" at the setup pose — the frame aims from the root at the point, and there is no direction to a point it stands on”<br>Also: “&lt;value&gt;: stop "&lt;value&gt;"” | Move at away from the first link's setup-pose root so an aim direction exists. |
7361
+ | <a id="CE_STOP_POINT_ON_LINK_LINE"></a>`CE_STOP_POINT_ON_LINK_LINE` | “&lt;who&gt;: "at" [&lt;stop.at.join(', ')&gt;] on "&lt;stop.against&gt;" lies on "&lt;links[0]&gt;"'s own line at the setup pose — inward is the turn from the link toward the point, and a point on the link's line has no side”<br>Also: “&lt;value&gt;: stop "&lt;value&gt;"” | Move at off the first link's setup-pose line so inward has a side. |
7362
+
7363
+
7364
+ #### 5.1.14 Deform generators
7365
+
7366
+ | Code | Fixed message text and alternatives | What to change |
7367
+ | --- | --- | --- |
7368
+ | <a id="CE_DEFORM_TRANSFORM_OBJECT"></a>`CE_DEFORM_TRANSFORM_OBJECT` | “&lt;where&gt;: "transform" is &lt;JSON.stringify(transform)&gt;; it is an object with a "kind"” | Write transform as an object with a kind. |
7369
+ | <a id="CE_DEFORM_TRANSFORM_KIND"></a>`CE_DEFORM_TRANSFORM_KIND` | “&lt;where&gt;: "transform" has kind &lt;JSON.stringify(kind)&gt;; this spec evaluates &lt;DEFORM_TRANSFORM_KINDS.join(', ')&gt;. A model that is none of those is still authorable as a "vertices" run.”<br>Here the values named in the message include: “yaw”, “bend”, “wave”, “pitch”, “affine”. | Choose a supported transform kind, or author the deformation as a vertices run. |
7370
+ | <a id="CE_DEFORM_DEPTH_RADIUS_CONFLICT"></a>`CE_DEFORM_DEPTH_RADIUS_CONFLICT` | “&lt;where&gt;: transform &lt;kind&gt; states both "depth": true and a radius &lt;JSON.stringify(t.radius)&gt;. They are two answers to how far forward each vertex sits — a cylinder derives it, a map states it — and a key carrying both leaves a reader unable to say which one the output came from. Drop one.” | Choose depth:true or a radius and remove the other. |
7371
+ | <a id="CE_DEFORM_DEPTH_MAP_REQUIRED"></a>`CE_DEFORM_DEPTH_MAP_REQUIRED` | “&lt;where&gt;: transform &lt;kind&gt; says "depth": true and this attachment has no depth map. The map is named on the attachment's generator, as `"depth": { "image": …, "near": …, "zScale": … }`, because it describes the art rather than this key. Name it there, or give this key a radius.” | Declare the attachment generator depth map or give this transform a radius. |
7372
+ | <a id="CE_DEFORM_DEPTH_SAMPLE_COUNT"></a>`CE_DEFORM_DEPTH_SAMPLE_COUNT` | “&lt;where&gt;: transform &lt;kind&gt; has &lt;depth.length&gt; sampled depths for &lt;count&gt; vertices” | Report this compiler defect with the inputs and printed sampled-depth and vertex counts; do not edit generated samples. |
7373
+ | <a id="CE_DEFORM_RADIUS_POSITIVE"></a>`CE_DEFORM_RADIUS_POSITIVE` | “&lt;where&gt;: transform &lt;kind&gt; has radius &lt;radius&gt;; it is the radius of the cylinder the part is painted on, so a positive number” | State a positive cylinder radius. |
7374
+ | <a id="CE_DEFORM_VERTEX_OUTSIDE_CYLINDER"></a>`CE_DEFORM_VERTEX_OUTSIDE_CYLINDER` | “&lt;where&gt;: transform &lt;kind&gt; has radius &lt;radius&gt;, and vertex &lt;v&gt; sits at &lt;kind === 'yaw' ? 'x' : 'y'&gt;=&lt;setup[2 * v + along]&gt;, which is &lt;round(Math.abs(u) - radius)&gt; past it (about=&lt;about&gt;). The cylinder has no surface there, so its depth would be 0 and the projection would be a different model at that vertex. Raise the radius to where the part actually sits, or move the vertex.” | Raise radius to include the measured vertex or move that vertex within the cylinder. |
7375
+ | <a id="CE_DEFORM_AFFINE_DETERMINANT"></a>`CE_DEFORM_AFFINE_DETERMINANT` | “&lt;where&gt;: transform affine has scale [&lt;scale[0]&gt;, &lt;scale[1]&gt;], whose determinant is &lt;round(det)&gt;. At or below zero the map mirrors or collapses the geometry and EVERY triangle reverses its winding, which is the fold A39_DEFORM_KEEPS_TRIANGLE_WINDING refuses. A positive determinant is what makes this kind incapable of folding a mesh.” | Use affine scale with a positive determinant so geometry neither mirrors nor collapses. |
7376
+ | <a id="CE_DEFORM_WAVELENGTH_ZERO"></a>`CE_DEFORM_WAVELENGTH_ZERO` | “&lt;where&gt;: transform wave has wavelength 0; one period cannot be zero long” | State a non-zero wavelength. |
7377
+ | <a id="CE_DEFORM_BEND_POWER_WHOLE"></a>`CE_DEFORM_BEND_POWER_WHOLE` | “&lt;where&gt;: transform bend has power &lt;power&gt;; it is a whole number ≥ 1 (1 is an affine shear, 2 a cantilever that is flat at "from"). A fractional power is not evaluated because it has no value on the side of "from" the part does not reach.” | Use a whole bend power of at least 1. |
7378
+ | <a id="CE_DEFORM_BEND_ENDS_EQUAL"></a>`CE_DEFORM_BEND_ENDS_EQUAL` | “&lt;where&gt;: transform bend has from &lt;from&gt; and to &lt;to&gt;; they are the two ends of the bend, so they differ” | Give bend from and to different values. |
7379
+ | <a id="CE_DEFORM_TRANSFORM_QUANTISED_IDENTITY"></a>`CE_DEFORM_TRANSFORM_QUANTISED_IDENTITY` | “&lt;where&gt;: transform &lt;kind&gt; states &lt;stated&gt;, and every one of this attachment's &lt;count&gt; vertices evaluates to an offset of 0 — the largest value the closed form reached at any of them is &lt;band.toExponential(3)&gt;, which quantises to 0 on the 1e-6 grid a model is evaluated on. So the key states a deformation and emits the identity, and nothing downstream can tell it apart from a key that meant the setup pose. &lt;sampledTo&gt;. A key that MEANS the identity states it in its own parameters (&lt;identitySpelling&gt;) or carries no run at all.”<br>“A scale about a fixed point moves nothing that SITS on it, so every vertex this attachment has lies at about=[&lt;about[0]&gt;, &lt;about[1]&gt;] on the axis the scale changes — the geometry has collapsed onto the point the key holds still”<br>“amount 0”<br>“amount=&lt;amount&gt; from=&lt;from&gt; to=&lt;to&gt; power=&lt;power&gt; along=&lt;an&gt; axis=&lt;axis === 0 ? 'x' : 'y'&gt;”<br>“amplitude 0”<br>“amplitude=&lt;amplitude&gt; wavelength=&lt;wavelength&gt; phase=&lt;phase&gt; along=&lt;an&gt; axis=&lt;axis === 0 ? 'x' : 'y'&gt;”<br>“degrees 0”<br>“scale [1, 1]”<br>“scale=[&lt;scale[0]&gt;, &lt;scale[1]&gt;]&lt;a.about === undefined ? '' : ` about=[${about[0]}, ${about[1]}]`&gt;”<br>“{Every vertex sits at &lt;an&gt;=&lt;distinct[0]&gt;, so one value of the sinusoid covers the whole attachment and this phase is where that one value crosses zero. A wave needs the coordinate it reads to VARY across the geometry; a part that displaces as a whole is a bone, not a deform / The closest two distinct &lt;an&gt; coordinates in this attachment are &lt;round(gap)&gt; apart, and a sinusoid has to be sampled to exist: a wavelength of at least 4x that (&lt;round(4 * gap)&gt;) to read as a wave at all and 8x (&lt;round(8 * gap)&gt;) to read as a curve, where this key states &lt;round(wavelength / gap)&gt;x. At 2x every sample lands on the same pair of phases, and at the zero crossings that pair is (0, 0). `gallery/nod`'s README carries that rule and the measured table behind it}”<br>“{Every vertex sits at &lt;an&gt;=&lt;from&gt;, which is "from" — the end the bend is anchored at, where the displacement is 0 by construction. The span the key names does not cross the part it is keyed on / The furthest any vertex reaches into the span is u=&lt;round(reach)&gt; of 1, and u^&lt;power&gt; of that is &lt;(reach ** power).toExponential(3)&gt; — so the part occupies only the flat end of the curve. Move "to" to where the geometry actually ends, or lower the power}”<br>“{The turn is &lt;degrees&gt;°, and a projection of it can only vanish where every vertex shares one &lt;kind === 'yaw' ? 'x' : 'y'&gt; AND one depth — check the depth map's sampled range in the mesh report, which is 0 wide when the sheet is flat where this part sits / The turn is &lt;degrees&gt;°, and a projection of it can only vanish where every vertex shares one &lt;kind === 'yaw' ? 'x' : 'y'&gt; — check that this attachment's setup geometry is the shape the radius says it is}”<br>“{depth=true degrees=&lt;degrees&gt;&lt;t.about === undefined ? '' : ` about=${about}`&gt; / radius=&lt;radius&gt; degrees=&lt;degrees&gt;&lt;t.about === undefined ? '' : ` about=${about}`&gt;}”<br>Also: “axis=[&lt;value&gt;, &lt;value&gt;] from=&lt;value&gt; to=&lt;value&gt; shape=&lt;value&gt;”<br>“mask=&lt;value&gt;”<br>“&lt;value&gt; envelope(&lt;value&gt;)”<br>Here the values named in the message include: “linear”, “smooth”. | Use parameters with a measured non-zero result, explicitly state identity parameters, or omit the run. |
7380
+ | <a id="CE_DEFORM_ENVELOPE_ZERO_WEIGHT"></a>`CE_DEFORM_ENVELOPE_ZERO_WEIGHT` | “&lt;where&gt;: transform &lt;kind&gt; states &lt;stated&gt; and moves &lt;plain.filter((d, i) =&gt; i % 2 === 0 &amp;&amp; (d !== 0 \|\| plain[i + 1] !== 0)).length&gt; of &lt;count&gt; vertices, and envelope &lt;weighed.stated&gt; weighs every one of them 0 — so the key states a deformation and emits the identity. &lt;weighed.reach&gt;”<br>“The mask "&lt;mask&gt;" weighs &lt;carried&gt; of &lt;count&gt; vertices above 0.”<br>“axis=[&lt;axis[0]&gt;, &lt;axis[1]&gt;] from=&lt;from&gt; to=&lt;to&gt; shape=&lt;shape&gt;”<br>“mask=&lt;mask&gt;”<br>“{The attachment has no vertices. / Along [&lt;axis[0]&gt;, &lt;axis[1]&gt;] this attachment's vertices sit at &lt;round(lo)&gt; to &lt;round(hi)&gt;, and the ramp rises from &lt;from&gt; (weight 0) to &lt;to&gt; (weight 1) — move "from" and "to" onto the part.}”<br>Also: “amplitude=&lt;value&gt; wavelength=&lt;value&gt; phase=&lt;value&gt; along=&lt;value&gt; axis=&lt;value&gt;”<br>“{depth=true degrees=&lt;value&gt;&lt;value&gt; / radius=&lt;value&gt; degrees=&lt;value&gt;&lt;value&gt;}”<br>“{ / about=[&lt;value&gt;, &lt;value&gt;]}”<br>“amount=&lt;value&gt; from=&lt;value&gt; to=&lt;value&gt; power=&lt;value&gt; along=&lt;value&gt; axis=&lt;value&gt;”<br>“&lt;value&gt; envelope(&lt;value&gt;)”<br>“scale=[&lt;value&gt;, &lt;value&gt;]&lt;value&gt;”<br>Here the values named in the message include: “linear”, “smooth”. | Place the envelope ramp or mask where it weights moved vertices above 0, or remove the ineffective key. |
7381
+ | <a id="CE_DEFORM_ENVELOPE_NO_EFFECT"></a>`CE_DEFORM_ENVELOPE_NO_EFFECT` | “&lt;where&gt;: transform &lt;kind&gt; states envelope &lt;weighed.stated&gt;, and it changes no emitted number: every vertex the model moves takes weight 1 (&lt;weighed.full&gt; of &lt;count&gt; vertices at 1, &lt;weighed.zero&gt; at 0), so the run is the un-enveloped one and the envelope is a field a reader would credit for an output it did not shape. &lt;weighed.reach&gt;”<br>“The mask "&lt;mask&gt;" weighs &lt;carried&gt; of &lt;count&gt; vertices above 0.”<br>“axis=[&lt;axis[0]&gt;, &lt;axis[1]&gt;] from=&lt;from&gt; to=&lt;to&gt; shape=&lt;shape&gt;”<br>“mask=&lt;mask&gt;”<br>“{The attachment has no vertices. / Along [&lt;axis[0]&gt;, &lt;axis[1]&gt;] this attachment's vertices sit at &lt;round(lo)&gt; to &lt;round(hi)&gt;, and the ramp rises from &lt;from&gt; (weight 0) to &lt;to&gt; (weight 1) — move "from" and "to" onto the part.}”<br>Here the values named in the message include: “linear”, “smooth”. | Remove the ineffective envelope, or place its transition over vertices the model moves. |
7382
+ | <a id="CE_DEFORM_ENVELOPE_OBJECT"></a>`CE_DEFORM_ENVELOPE_OBJECT` | “&lt;where&gt;: transform field "envelope" is &lt;JSON.stringify(envelope)&gt;; it is an object — a ramp `{ "axis", "from", "to", "shape" }` or a mask `{ "mask" }`” | Write envelope as a ramp object or a mask object. |
7383
+ | <a id="CE_DEFORM_ENVELOPE_MASK_RAMP_CONFLICT"></a>`CE_DEFORM_ENVELOPE_MASK_RAMP_CONFLICT` | “&lt;where&gt;: transform field "envelope" states "mask" &lt;JSON.stringify(e.mask)&gt; beside the ramp's &lt;rampStated.map((f) =&gt; `"${f}"`).join(', ')&gt;. They are two answers to one question — what weight each vertex takes — and a key carrying both leaves a reader unable to say which one the output came from. Drop one.”<br>Here the values named in the message include: “axis”, “shape”. | Choose envelope.mask or the ramp fields and remove the other form. |
7384
+ | <a id="CE_DEFORM_ENVELOPE_WEIGHT_UNSTATED"></a>`CE_DEFORM_ENVELOPE_WEIGHT_UNSTATED` | “&lt;where&gt;: transform field "envelope" is &lt;JSON.stringify(envelope)&gt;, which states no weight at all. It is a ramp `{ "axis", "from", "to", "shape" }` or a mask `{ "mask" }`; a key that weighs every vertex 1 carries no envelope.” | State a ramp or mask, or omit envelope for uniform weight 1. |
7385
+ | <a id="CE_DEFORM_ENVELOPE_SOFT_REQUIRED"></a>`CE_DEFORM_ENVELOPE_SOFT_REQUIRED` | “&lt;where&gt;: transform field "envelope.mask" is &lt;JSON.stringify(mask)&gt;, and this attachment has no "soft" block, so the mask names nothing. An envelope's mask is the attachment's own soft mask (AUTHORING §3.4.6), the one its generator sampled at every vertex when the mesh was built; give the generator a "soft" block, or state a ramp instead.” | Give the attachment generator a soft block or use a ramp envelope. |
7386
+ | <a id="CE_DEFORM_ENVELOPE_MASK_MISMATCH"></a>`CE_DEFORM_ENVELOPE_MASK_MISMATCH` | “&lt;where&gt;: transform field "envelope.mask" is &lt;JSON.stringify(mask)&gt;, and this attachment's soft mask is &lt;JSON.stringify(soft.mask)&gt;, so the mask names nothing it was built with. An envelope reads the mask the generator sampled at every vertex, and only that one.” | Name the soft mask this attachment's generator sampled. |
7387
+ | <a id="CE_DEFORM_SOFT_SAMPLE_COUNT"></a>`CE_DEFORM_SOFT_SAMPLE_COUNT` | “&lt;where&gt;: the soft mask "&lt;mask&gt;" has &lt;soft.levels.length&gt; sampled levels for &lt;count&gt; vertices” | Report this compiler defect with the inputs and printed mask-level and vertex counts; do not edit generated samples. |
7388
+ | <a id="CE_DEFORM_ENVELOPE_SHAPE"></a>`CE_DEFORM_ENVELOPE_SHAPE` | “&lt;where&gt;: transform field "envelope.shape" is &lt;JSON.stringify(e.shape)&gt;; it is one of &lt;DEFORM_ENVELOPE_SHAPES.map((name) =&gt; JSON.stringify(name)).join(', ')&gt; — how the weight rises from 0 at "from" to 1 at "to": "linear" is u, "smooth" is u²(3 − 2u)” | Use linear or smooth for envelope.shape. |
7389
+ | <a id="CE_DEFORM_ENVELOPE_AXIS_UNIT"></a>`CE_DEFORM_ENVELOPE_AXIS_UNIT` | “&lt;where&gt;: transform field "envelope.axis" is [&lt;axis[0]&gt;, &lt;axis[1]&gt;], whose length is &lt;round(length)&gt;; it is a unit direction, length 1 on the model's 1e-6 grid. A longer or shorter one would scale every position the ramp compares with "from" and "to" — divide it by its length, and state "from" and "to" along the unit one.” | Divide envelope.axis by its length and state from/to along the resulting unit direction. |
7390
+ | <a id="CE_DEFORM_ENVELOPE_ENDS_EQUAL"></a>`CE_DEFORM_ENVELOPE_ENDS_EQUAL` | “&lt;where&gt;: transform fields "envelope.from" and "envelope.to" are both &lt;from&gt;; they are where the weight is 0 and where it is 1, so they differ — a ramp of no length is a step, and a step is the edge a model exists not to leave.” | Give envelope.from and envelope.to different values. |
7391
+ | <a id="CE_DEFORM_ENVELOPE_WEIGHT_RANGE"></a>`CE_DEFORM_ENVELOPE_WEIGHT_RANGE` | “&lt;where&gt;: transform field "&lt;field&gt;" weighs vertex &lt;v&gt; at &lt;w&gt;; an envelope's weight is in [0, 1] — 0 leaves the vertex where it is and 1 moves it the whole way the model says, and nothing past either end is a weight.”<br>Also: “{envelope.shape / envelope.mask}” | State envelope weights in [0, 1]. |
7392
+ | <a id="CE_DEFORM_FIELD_NUMBER_FINITE"></a>`CE_DEFORM_FIELD_NUMBER_FINITE` | “&lt;where&gt;: transform field "&lt;field&gt;" is &lt;JSON.stringify(value)&gt;; it is a finite number the spec has to state”<br>Also: “&lt;value&gt;[0]”<br>“&lt;value&gt;[1]”<br>Here the values named in the message include: “envelope.from”, “power”, “phase”, “about”, “scale”, “radius”, “amount”, “degrees”, “amplitude”, “wavelength”, “envelope.to”, “envelope.axis”. | State a finite number for the printed transform field. |
7393
+ | <a id="CE_DEFORM_FIELD_PAIR"></a>`CE_DEFORM_FIELD_PAIR` | “&lt;where&gt;: transform field "&lt;field&gt;" is &lt;JSON.stringify(value)&gt;; it is a pair, [x, y]”<br>Here the values named in the message include: “scale”, “about”, “envelope.axis”. | State [x, y] for the printed transform field. |
7394
+ | <a id="CE_DEFORM_COORDINATE_NAME"></a>`CE_DEFORM_COORDINATE_NAME` | “&lt;where&gt;: transform &lt;kind&gt; has &lt;name&gt;=&lt;JSON.stringify(value)&gt;; it is "x" or "y"”<br>Here the values named in the message include: “axis”, “along”. | Use x or y for the printed coordinate selector. |
7395
+ | <a id="CE_DEFORM_SAME_READ_DISPLACE_AXIS"></a>`CE_DEFORM_SAME_READ_DISPLACE_AXIS` | “&lt;where&gt;: transform &lt;kind&gt; reads &lt;String(along)&gt; and displaces &lt;String(axis)&gt; — the same coordinate, which is a stretch rather than a bend or a wave. An affine scale states that, and states the determinant that proves it keeps every triangle's winding.” | Use different read and displacement coordinates, or state the stretch as affine scale. |
7396
+
7397
+
7398
+ #### 5.1.15 Track generators
7399
+
7400
+ | Code | Fixed message text and alternatives | What to change |
7401
+ | --- | --- | --- |
7402
+ | <a id="CE_TRACK_DERIVE_OBJECT"></a>`CE_TRACK_DERIVE_OBJECT` | “&lt;where&gt;: "derive" is &lt;JSON.stringify(derive)&gt;; it is an object with a "kind"” | Write derive as an object with a kind. |
7403
+ | <a id="CE_TRACK_DERIVE_KIND"></a>`CE_TRACK_DERIVE_KIND` | “&lt;where&gt;: "derive" has kind &lt;JSON.stringify(kind)&gt;; this spec evaluates &lt;TRACK_DERIVE_KINDS.join(', ')&gt;. A model that is none of those is still authorable as a per-member "v" map, or as one track per member.”<br>Here the values named in the message include: “yaw”, “pitch”. | Use a supported derive kind, a per-member v map, or one authored track per member. |
7404
+ | <a id="CE_TRACK_CARRIED_PROJECTION"></a>`CE_TRACK_CARRIED_PROJECTION` | “&lt;where&gt;: derive &lt;kind&gt; states carried=&lt;JSON.stringify(turn.carried)&gt; on a "&lt;property&gt;" track, and the foreshortening reads no depth difference — it is cos(α − t)/cos α, where α is the member's own angle off the axis. "carried" belongs on the "&lt;projections.shift&gt;" track, whose shared shift is the thing it names.” | Put carried on the displacement projection rather than the foreshortening track. |
7405
+ | <a id="CE_TRACK_FORESHORTEN_DEPTH"></a>`CE_TRACK_FORESHORTEN_DEPTH` | “&lt;where&gt;: derive &lt;kind&gt; projects onto "&lt;property&gt;" and member "&lt;member.name&gt;" states depth &lt;depth&gt;. Foreshortening is cos(α − t)/cos α with α = atan2(coordinate, depth), which needs the part to be IN FRONT of the axis; at or behind it there is no front surface to narrow. A part behind the axis still takes the "&lt;projections.shift&gt;" projection, where a negative depth is exactly what swings it the other way.” | State positive depth for the foreshortening projection; negative depth belongs to displacement. |
7406
+ | <a id="CE_TRACK_FORESHORTEN_EDGE_ON"></a>`CE_TRACK_FORESHORTEN_EDGE_ON` | “&lt;where&gt;: derive &lt;kind&gt; turns member "&lt;member.name&gt;" (&lt;projections.coordinate&gt;=&lt;u&gt;, depth=&lt;depth&gt;) past its own edge: α = &lt;round(alpha)&gt; rad and the turn is &lt;round(rad)&gt; rad, so cos(α − t) is &lt;round(Math.cos(alpha - rad))&gt; and the scale would be &lt;round(scale)&gt;. A scale at or below 0 mirrors the drawing rather than narrowing it. The part has turned edge-on — the turn is past what this construction carries, and FACE §8 is the page that picks a construction from the angle.” | Keep the turn within this construction's positive scale range or choose the construction described in FACE §8. |
7407
+ | <a id="CE_TRACK_PROPERTY_PROJECTION"></a>`CE_TRACK_PROPERTY_PROJECTION` | “&lt;where&gt;: derive &lt;kind&gt; has no projection onto "&lt;property&gt;". It projects onto "&lt;p.shift&gt;" (the displacement, FACE §3) and "&lt;p.foreshorten&gt;" (the narrowing, FACE §5), and onto nothing else — a turn about one axis moves nothing along it, so a paired "translate"/"scale" would need a second channel this model does not state. State the axis, or write the values as a per-member "v" map.” | Use the derive kind's printed displacement or foreshortening property, or a per-member v map. |
7408
+ | <a id="CE_TRACK_GROUP_SHARED_DEPTH"></a>`CE_TRACK_GROUP_SHARED_DEPTH` | “&lt;where&gt;: derive &lt;kind&gt; states one depth &lt;depth&gt; for &lt;members.length&gt; members (&lt;members.map((m) =&gt; m.name).join(', ')&gt;). One number for every member is the shared value a plain "v" already keys — state a depth per member, as { "member": z, … }.” | State a depth per group member as a member-name map. |
7409
+ | <a id="CE_TRACK_DEPTH_SHAPE"></a>`CE_TRACK_DEPTH_SHAPE` | “&lt;where&gt;: derive &lt;kind&gt; has depth &lt;JSON.stringify(depth)&gt;; it is a number on a bone track and { "member": z, … } on a group track” | Use numeric depth on a bone track and a member-name depth map on a group track. |
7410
+ | <a id="CE_TRACK_DEPTH_MEMBER_UNKNOWN"></a>`CE_TRACK_DEPTH_MEMBER_UNKNOWN` | “&lt;where&gt;: derive &lt;kind&gt; states a depth for "&lt;name&gt;", which this track does not key (its members are: &lt;members.map((m) =&gt; m.name).join(', ')&gt;)” | Remove the depth entry for a member this track does not key. |
7411
+ | <a id="CE_TRACK_DEPTH_MEMBER_REQUIRED"></a>`CE_TRACK_DEPTH_MEMBER_REQUIRED` | “&lt;where&gt;: derive &lt;kind&gt; states no depth for member "&lt;member&gt;" (it states: &lt;stated.length ? stated.join(', ') : 'nothing'&gt;). A depth is refused rather than defaulted: a member silently at depth 0 would be keyed with a DIFFERENT model from the ones beside it, and that is exactly the error a table of six is written to make visible.” | State a finite depth for each member keyed by the track. |
7412
+ | <a id="CE_TRACK_FIELD_NUMBER_FINITE"></a>`CE_TRACK_FIELD_NUMBER_FINITE` | “&lt;where&gt;: derive field "&lt;field&gt;" is &lt;JSON.stringify(value)&gt;; it is a finite number the spec has to state”<br>Also: “depth.&lt;value&gt;”<br>Here the values named in the message include: “about”, “carried”, “degrees”. | State a finite number for the printed derive field. |
7413
+
7414
+
7415
+ #### 5.1.16 Atlas packing
7416
+
7417
+ | Code | Fixed message text and alternatives | What to change |
7418
+ | --- | --- | --- |
7419
+ | <a id="CE_ATLAS_INTERNAL_FOOTPRINT_OVERLAP"></a>`CE_ATLAS_INTERNAL_FOOTPRINT_OVERLAP` | “internal: the footprint pass placed a &lt;shape.width&gt;x&lt;shape.height&gt; cell at &lt;put.x&gt;,&lt;put.y&gt; over the footprint of the &lt;other.shape.width&gt;x&lt;other.shape.height&gt; cell at &lt;other.x&gt;,&lt;other.y&gt;” | Report this compiler bug with the inputs, packing options and printed overlapping cells. |
7420
+ | <a id="CE_ATLAS_PACKING_STALLED"></a>`CE_ATLAS_PACKING_STALLED` | “packing stalled with &lt;remaining.length&gt; region(s) left and an empty &lt;maxEdge&gt;x&lt;maxEdge&gt; page” | Report this packer defect with the inputs, page size and remaining-region count. |
7421
+ | <a id="CE_ATLAS_SPILL_UNPACKABLE"></a>`CE_ATLAS_SPILL_UNPACKABLE` | “page &lt;pageIndex + 1&gt; of the spill holds &lt;onPage.length&gt; region(s) that no page fits” | Report this packer defect with the inputs, packing options and printed spill page. |
7422
+ | <a id="CE_ATLAS_PAGE_EDGES_VALUE"></a>`CE_ATLAS_PAGE_EDGES_VALUE` | “--page-edges &lt;JSON.stringify(String(opts.pageEdges))&gt;; known values: &lt;PAGE_EDGES.join(', ')&gt;”<br>Here the values named in the message include: “pot”, “free”. | Choose a printed --page-edges value. |
7423
+ | <a id="CE_ATLAS_PACK_SHAPE_VALUE"></a>`CE_ATLAS_PACK_SHAPE_VALUE` | “--pack-shape &lt;JSON.stringify(String(opts.shape))&gt;; known values: &lt;PACK_SHAPES.join(', ')&gt;”<br>Here the values named in the message include: “rect”, “polygon”. | Choose a printed --pack-shape value. |
7424
+ | <a id="CE_ATLAS_PAGE_SIZE_POSITIVE_INTEGER"></a>`CE_ATLAS_PAGE_SIZE_POSITIVE_INTEGER` | “--page-size must be a positive integer, got &lt;String(opts.pageSize)&gt;” | Use a positive integer for --page-size. |
7425
+ | <a id="CE_ATLAS_PADDING_NONNEGATIVE_INTEGER"></a>`CE_ATLAS_PADDING_NONNEGATIVE_INTEGER` | “--padding must be a non-negative integer, got &lt;String(opts.padding)&gt;” | Use a non-negative integer for --padding. |
7426
+ | <a id="CE_ATLAS_IMAGES_REQUIRED"></a>`CE_ATLAS_IMAGES_REQUIRED` | “nothing to pack: this compile emitted no images” | Provide a build with emitted images before requesting atlas packing. |
7427
+ | <a id="CE_ATLAS_REGION_EXCEEDS_PAGE"></a>`CE_ATLAS_REGION_EXCEEDS_PAGE` | “"&lt;sorted[i].region&gt;" is &lt;sorted[i].width&gt;x&lt;sorted[i].height&gt; and with --padding &lt;padding&gt; needs a &lt;cells[i].w&gt;x&lt;cells[i].h&gt; cell, which does not fit a &lt;maxEdge&gt;x&lt;maxEdge&gt; page (&lt;sorted[i].absPath&gt;). Raise --page-size, lower --padding, or leave this build unpacked — a packer cannot split one drawing across two pages.” | Raise --page-size, lower --padding, or leave the build unpacked. |
7428
+ | <a id="CE_ATLAS_IMAGE_DIMENSIONS_CHANGED"></a>`CE_ATLAS_IMAGE_DIMENSIONS_CHANGED` | “"&lt;place.region&gt;" measured &lt;input.width&gt;x&lt;input.height&gt; from its PNG header and decodes to &lt;source.width&gt;x&lt;source.height&gt; (&lt;input.absPath&gt;)” | Use the same PNG throughout the build; if unchanged input reproduces the mismatch, report it with the named file. |
7429
+
7430
+
7431
+ #### 5.1.17 Model writer defects
7432
+
7433
+ | Code | Fixed message text and alternatives | What to change |
7434
+ | --- | --- | --- |
7435
+ | <a id="CE_MODEL_INTERNAL_FIELD_UNREPRESENTABLE"></a>`CE_MODEL_INTERNAL_FIELD_UNREPRESENTABLE` | “internal: the model document has no place for field "&lt;key&gt;" of &lt;where&gt;; it writes [&lt;keys.join(', ')&gt;]”<br>Here the values named in the message include: “xy”, “slots”, “bones”, “blend”, “lengths”, “weighted”, “editorColor”, “attachments”, “skinRequired”, “ik”, “box”, “uvs”, “hull”, “icon”, “dark”, “name”, “path”, “kind”, “width”, “edges”, “float”, “atlas”, “start”, “count”, “audio”, “color”, “setup”, “shearY”, “closed”, “parent”, “shearX”, “events”, “source”, “height”, “convex”, “slider”, “string”, “digits”, “scaleY”, “deform”, “scaleX”, “volume”, “balance”, “offsetX”, “inverse”, “physics”, “offsetY”, “sequence”, “duration”, “bindings”, “vertices”, “rotation”, “timelines”, “triangles”, “transform”, “drawOrder”, “vertexCount”, “inheritMode”, “constraints”, “constantSpeed”, “originalWidth”, “originalHeight”. | Report this compiler bug with the inputs and named model field; the model writer lacks its representation. |
7436
+ | <a id="CE_MODEL_INTERNAL_NONFINITE_NUMBER"></a>`CE_MODEL_INTERNAL_NONFINITE_NUMBER` | “internal: the model document cannot carry &lt;value&gt; at &lt;where&gt;; JSON writes it as null”<br>Also: “no region "&lt;value&gt;" in &lt;value&gt;”<br>“manifest declares `image: null` and no states”<br>Here the values named in the message include: “/”, “rig”, “motion”, “physics”. | Report this compiler bug with the inputs and named model path; non-finite data reached the writer. |
7437
+ | <a id="CE_MODEL_INTERNAL_NEGATIVE_ZERO"></a>`CE_MODEL_INTERNAL_NEGATIVE_ZERO` | “internal: the model document cannot carry -0 at &lt;where&gt;; JSON writes it as 0” | Report this compiler bug with the inputs and named model path; -0 reached the writer. |
7438
+ | <a id="CE_MODEL_INTERNAL_UNDEFINED_ELEMENT"></a>`CE_MODEL_INTERNAL_UNDEFINED_ELEMENT` | “internal: the model document cannot carry undefined at &lt;where&gt;[&lt;i&gt;]; JSON writes it as null” | Report this compiler bug with the inputs and named model array path; undefined reached the writer. |
7439
+ | <a id="CE_MODEL_INTERNAL_NONPLAIN_VALUE"></a>`CE_MODEL_INTERNAL_NONPLAIN_VALUE` | “internal: the model document cannot carry &lt;Object.prototype.toString.call(value)&gt; at &lt;where&gt;; it writes plain data only” | Report this compiler bug with the inputs and named model path; a non-plain value reached the writer. |
7440
+ | <a id="CE_MODEL_INTERNAL_ATTACHMENT_KIND"></a>`CE_MODEL_INTERNAL_ATTACHMENT_KIND` | “internal: the model document knows no attachment kind "&lt;String(entry.kind)&gt;" at &lt;where&gt;” | Report this compiler bug with the inputs and named attachment; the writer knows no representation for its kind. |
7441
+ | <a id="CE_MODEL_INTERNAL_REGION_SOURCE"></a>`CE_MODEL_INTERNAL_REGION_SOURCE` | “internal: the region at &lt;where&gt; carries &lt;entry.atlas === undefined ? 'neither an atlas rectangle nor a sequence' : 'both an atlas rectangle and a sequence'&gt;; a region states exactly one of the two, and a sequence holds a rectangle per frame (issue #935)” | Report this compiler bug with the inputs and named region; exactly one atlas rectangle or sequence must reach the writer. |
7442
+ | <a id="CE_MODEL_INTERNAL_ATLAS_FIELD_REQUIRED"></a>`CE_MODEL_INTERNAL_ATLAS_FIELD_REQUIRED` | “internal: the atlas rectangle at &lt;where&gt; has no &lt;key&gt;; it states all of [&lt;ATLAS_RECT_FIELDS.join(', ')&gt;]”<br>Here the values named in the message include: “width”, “height”, “offsetX”, “offsetY”, “originalWidth”, “originalHeight”. | Report this compiler bug with the inputs and named atlas rectangle field. |
7443
+ | <a id="CE_MODEL_INTERNAL_EDITOR_ORDER"></a>`CE_MODEL_INTERNAL_EDITOR_ORDER` | “internal: the model's editor order is not its own: &lt;problems.join('; ')&gt;”<br>Also: “editorOrder.skins[&lt;value&gt;] "&lt;value&gt;".slots”<br>“&lt;value&gt; lists [&lt;value&gt;], the model holds [&lt;value&gt;]”<br>Here the values named in the message include: “editorOrder.animations”. | Report this compiler bug with the inputs and printed editor-order faults. |
7444
+ | <a id="CE_MODEL_INTERNAL_DOCUMENT_FIELD"></a>`CE_MODEL_INTERNAL_DOCUMENT_FIELD` | “internal: the model document has no place for the model's field "&lt;key&gt;"; it writes [&lt;MODEL_DOCUMENT_FIELDS.join(', ')&gt;] and leaves out [&lt;MODEL_DOCUMENT_LEFT_OUT.join(', ')&gt;]”<br>Here the values named in the message include: “rig”, “skins”, “slots”, “stage”, “bones”, “events”, “images”, “meshes”, “physics”, “meshBones”, “pageGrids”, “setupWorld”, “animations”, “editorOrder”, “absentParts”, “constraints”, “droppedStates”, “referenceScale”, “deformTransforms”, “trackDerivations”. | Report this compiler bug with the inputs and named model-document field; the writer lacks its representation. |
7445
+
7446
+
7447
+ #### 5.1.18 Motion parser
7448
+
7449
+ | Code | Fixed message text and alternatives | What to change |
7450
+ | --- | --- | --- |
7451
+ | <a id="CE_MOTION_FIELD_SHAPE"></a>`CE_MOTION_FIELD_SHAPE` | “"lag" is seconds added to every key time of this track, so a finite number — a string is CONCATENATED onto each time and a boolean adds 1”<br>“"stagger" is the extra per-member delay inside a group, in seconds, so a finite number”<br>“4.3 writes this group as `&lt;group&gt;.&lt;constraint&gt;`, so the constraint name is the only target there is”<br>“&lt;group === 'ik' ? 'an ik' : 'a transform'&gt; timeline is an object of `{ constraint, keys }`”<br>“&lt;typeof v === 'object' ? 'an' : 'a'&gt; &lt;typeof v&gt;”<br>“&lt;where&gt;: `&lt;key&gt;` is &lt;describe(is)&gt;; &lt;hint&gt;”<br>“a &lt;group&gt; key is an object of `{ t, … }`”<br>“a deform key is an object of `{ t, vertices? \| transform? }`”<br>“a deform timeline is an object of `{ skin?, slot, attachment, keys }`”<br>“a deform timeline keys one attachment of one slot, named here”<br>“a draw-order key is an object of `{ t, offsets? }`”<br>“a duration is a length of time, so it is not negative”<br>“a key is an object of `{ t, v, … }`”<br>“a key states its time in seconds, as a finite number”<br>“a mix pair is `["&lt;from animation&gt;", "&lt;to animation&gt;", &lt;seconds&gt;]` — three entries, two names and a duration”<br>“a named easing is FOUR finite numbers — the graph-view handles [hx1, hy1, hx2, hy2]. Nothing downstream counts them, so a short or non-numeric array reaches the artifact as a curve with a `null` in it”<br>“a physics constraint drives one bone, named here”<br>“a physics constraint is an object naming the bone it drives and the components it drives it in”<br>“a sequence key is an object of `{ t, mode?, index?, delay? }`”<br>“a sequence mode is one of the &lt;SEQUENCE_MODES.length&gt; the format has — &lt;SEQUENCE_MODES.join(', ')&gt; (absent means "hold"). The parser reads `SequenceMode[mode]`, which is undefined for anything else, and stores mode bits 0: the key would load without a word and play as "hold"”<br>“a sequence timeline is an object of `{ skin?, slot, attachment, keys }`”<br>“a sequence timeline steps one attachment of one slot, named here”<br>“a setup colour is [r, g, b, a], four finite numbers in 0..1 — a channel that is not one is clamped to `NaN` and written into the slot as the text "NaN"”<br>“a setup entry is an object of `{ attachment?: string \| null, color?: [r, g, b, a] }` — to show nothing there write `"&lt;slot&gt;": { "attachment": null }`, and to show an attachment write `"&lt;slot&gt;": { "attachment": "&lt;name&gt;" }`”<br>“a track is an object naming one target, one property and its keys”<br>“a track states the property it keys — the table is AUTHORING §4.4”<br>“a track's "&lt;field&gt;" is the name of the &lt;field === 'slot' \|\| field === 'bone' ? field : `${field} it targets`&gt;”<br>“absent”<br>“an animation declares its duration in seconds, as a finite number — it is checked against the compiled last key (rule R7), and a comparison against a non-number is silently false”<br>“an animation is an object of `{ duration, tracks, … }`”<br>“an array of &lt;v.length&gt;”<br>“an event key is an object of `{ t, name, … }`”<br>“every tuning field of a physics constraint is a finite number — a non-number is rounded to `NaN` and emitted as `null`, which the runtime reads as zero”<br>“it is `{ "default": &lt;seconds&gt;, "pairs"?: [["&lt;from&gt;", "&lt;to&gt;", &lt;seconds&gt;], …] }`”<br>“it is a player hint, so true or false (absent means the player decides)”<br>“it is a table keyed by animation name, `{ "&lt;name&gt;": { "duration": …, "tracks": [...] } }` (write `{}` for a static rig)”<br>“it is a table keyed by constraint name, `{ "&lt;name&gt;": { "bone": … } }`”<br>“it is a table keyed by group name, `{ "&lt;group&gt;": ["&lt;member&gt;", …] }`”<br>“it is a table keyed by slot name, `{ "&lt;slot&gt;": { "attachment": … } }`”<br>“it is a table of named handles, `{ "&lt;name&gt;": [hx1, hy1, hx2, hy2] }` (write `{}` if this spec names none)”<br>“it is an array of `["&lt;from&gt;", "&lt;to&gt;", &lt;seconds&gt;]` triples”<br>“it is an array of `{ "constraint": "&lt;name&gt;", "keys": [...] }` entries — one per &lt;group&gt; constraint”<br>“it is an array of `{ &lt;target&gt;, property, keys }` tracks (write `[]` for an animation whose timelines are all in the families beside it)”<br>“it is an array of `{ slot, attachment, keys }` entries — one per skin/slot/attachment triple”<br>“it is an array of `{ slot, offset }` moves. Omit the field entirely to restore the setup draw order — a malformed one used to BE that restore key, silently”<br>“it is an array of `{ t, mode?, index?, delay? }` keys”<br>“it is an array of `{ t, name }` firings — one timeline per animation, naming no target”<br>“it is an array of `{ t, offsets? }` keys — one timeline per animation, naming no target”<br>“it is an array of `{ t, v }` keys”<br>“it is an array of keys, each a sparse edit of the setup geometry”<br>“it is an array of keys, each naming the same set of mix fields”<br>“it is an attachment name, or null for "show nothing"”<br>“it is how many places later the slot is drawn, so a number (negative moves it earlier)”<br>“it is prose for a reader”<br>“it is the 0-based frame this key starts on, so a whole number of at least 0 — the runtime stores it as `index &lt;&lt; 4`, which truncates a fraction (1.5 showed frame 1) and puts a negative one before the series”<br>“it is the attachment's placeholder name inside that skin and slot”<br>“it is the seconds each frame shows for, so a finite number of at least 0”<br>“it names an entry of this spec's `easings` table, or is "stepped"”<br>“it names the cut these keys were authored for”<br>“it names the rig this spec was authored against, and must equal that rig spec's own `name`”<br>“it names the skin the attachment lives in; absent means "default"”<br>“it names the slot this key moves”<br>“null”<br>“one moved slot is `{ "slot": "&lt;name&gt;", "offset": &lt;places later&gt; }`”<br>“the default mix duration is a finite number of seconds”<br>“the empty name is how a skeleton file spells a physics timeline that names no constraint, and a motion spec spells that "&lt;EVERY_GLOBAL_PHYSICS&gt;" — it drives every physics constraint that declares the keyed property global (`"strengthGlobal": true` for `strength`). Name one constraint, or write "&lt;EVERY_GLOBAL_PHYSICS&gt;"”<br>“the string &lt;JSON.stringify(v)&gt;”<br>Here the values named in the message include: “loopReverse”, “onceReverse”, “pingpongReverse”, “*”. | Repair the named motion field using the exact shape, type, value range or spelling printed after the semicolon; the complete alternatives below cover every parser field. |
7452
+ | <a id="CE_MOTION_PHYSICS_NAME_RESERVED"></a>`CE_MOTION_PHYSICS_NAME_RESERVED` | “&lt;where&gt;: `&lt;key&gt;` names a physics constraint "&lt;EVERY_GLOBAL_PHYSICS&gt;", and that name is reserved: a track's `"physics": "&lt;EVERY_GLOBAL_PHYSICS&gt;"` is the timeline that names no constraint and drives every one declaring the keyed property global, so a constraint called "&lt;EVERY_GLOBAL_PHYSICS&gt;" could not be keyed by name. Give it another name”<br>Also: “physics."&lt;value&gt;"”<br>Here the values named in the message include: “*”. | Give the declared physics constraint a name other than *; * is the global-physics timeline target. |
7453
+ | <a id="CE_MOTION_SEQUENCE_ADVANCE_ZERO_DELAY"></a>`CE_MOTION_SEQUENCE_ADVANCE_ZERO_DELAY` | “&lt;where&gt;: `&lt;kat&gt;` plays "&lt;mode&gt;" at a delay of 0{ — it states none, and the parser carries the previous key's (&lt;j === 0 ? 'there is none, so 0' : '0'&gt;) / }. The runtime advances the frame by `(time - keyTime) / delay`, which is Infinity at 0, and `Infinity \| 0` is 0 — so the key shows its first frame for as long as it lasts, which is "hold" spelt as "&lt;mode&gt;". State the seconds per frame, or write "hold"”<br>Also: “&lt;value&gt;.keys[&lt;value&gt;]”<br>“animations."&lt;value&gt;"”<br>“&lt;value&gt;.sequence[&lt;value&gt;]” | State positive seconds per frame for advancing sequence modes, or use hold. |
7454
+ | <a id="CE_MOTION_SPEC_OBJECT"></a>`CE_MOTION_SPEC_OBJECT` | “&lt;where&gt;: a motion spec must be a JSON object, and this file holds &lt;describe(raw)&gt;”<br>Also: “the string &lt;value&gt;”<br>“an array of &lt;value&gt;”<br>Here the values named in the message include: “null”, “absent”. | Write the motion spec root as a JSON object. |
7455
+ | <a id="CE_MOTION_SPEC_VERSION"></a>`CE_MOTION_SPEC_VERSION` | “&lt;where&gt;: unknown motion spec version: &lt;String(raw.spec)&gt;, expected "&lt;MOTION_SPEC_VERSION&gt;"”<br>Here the values named in the message include: “rigc-motion/1”. | Set spec to the motion version named in the error. |
7456
+ | <a id="CE_MOTION_ANIMATION_NAME_EMPTY"></a>`CE_MOTION_ANIMATION_NAME_EMPTY` | “&lt;where&gt;: an animation has an empty name” | Give the animation a non-empty name. |
7457
+
7458
+
7459
+ #### 5.1.19 Spine emitter defects
7460
+
7461
+ | Code | Fixed message text and alternatives | What to change |
7462
+ | --- | --- | --- |
7463
+ | <a id="CE_EMIT_INTERNAL_WEIGHT_BONE_UNKNOWN"></a>`CE_EMIT_INTERNAL_WEIGHT_BONE_UNKNOWN` | “internal: a weighted vertex binds bone "&lt;bone&gt;", which is not in the model's bone list” | Report this compiler bug with the inputs and named bone; an unresolved weight reached the Spine emitter. |
7464
+ | <a id="CE_EMIT_INTERNAL_CONSTRAINT_FIELDS"></a>`CE_EMIT_INTERNAL_CONSTRAINT_FIELDS` | “internal: &lt;model.kind&gt; constraint "&lt;model.name&gt;" carries &lt;stray.join(', ')&gt;, which the emitter has no place for” | Report this compiler bug with the inputs and named constraint fields; the Spine emitter cannot represent them. |
7465
+ | <a id="CE_EMIT_INTERNAL_DRAW_ORDER_SHAPE"></a>`CE_EMIT_INTERNAL_DRAW_ORDER_SHAPE` | “internal: a draw-order key at t=&lt;key.time&gt; carries offsets that are not slot/offset moves” | Report this compiler bug with the inputs and named key time; malformed moves reached the Spine emitter. |
7466
+ | <a id="CE_EMIT_INTERNAL_DRAW_ORDER_SLOT_UNKNOWN"></a>`CE_EMIT_INTERNAL_DRAW_ORDER_SLOT_UNKNOWN` | “internal: a draw-order key at t=&lt;key.time&gt; moves slot "&lt;slot&gt;", which is not in the model's slot list” | Report this compiler bug with the inputs and named slot; an unresolved draw-order move reached the Spine emitter. |
7467
+ | <a id="CE_EMIT_INTERNAL_ANIMATION_UNKNOWN"></a>`CE_EMIT_INTERNAL_ANIMATION_UNKNOWN` | “internal: the animation order named "&lt;name&gt;", which is not in the model” | Report this compiler bug with the inputs and named animation; the emitter's animation order names no model animation. |
7468
+
7469
+
7470
+ #### 5.1.20 Shared spec field refusals
7471
+
7472
+ | Code | Fixed message text and alternatives | What to change |
7473
+ | --- | --- | --- |
7474
+ | <a id="CE_KEYS_UNKNOWN_FIELD"></a>`CE_KEYS_UNKNOWN_FIELD` | “&lt;where&gt;: &lt;what&gt; has &lt;strays.length === 1 ? 'a key' : `${strays.length} keys`&gt; this compiler does not read: &lt;named.join(', ')&gt;. Nothing reads such a key, so it would be dropped from the emitted skeleton in silence — fix the spelling or remove it. {This shape has no fields at all. / Known here: &lt;[...known].sort().join(', ')&gt;.}”<br>“{"&lt;key&gt;" / "&lt;key&gt;" (did you mean &lt;near.map((n) =&gt; `"${n}"`).join(', ')&gt;?)}”<br>Also: “skin "&lt;value&gt;" slot "&lt;value&gt;" attachment "&lt;value&gt;"”<br>“&lt;value&gt; generator.bones[&lt;value&gt;]”<br>“{constraint "&lt;value&gt;" / constraints[&lt;value&gt;]}”<br>“&lt;value&gt;.transform.envelope”<br>“&lt;value&gt; weights[&lt;value&gt;][&lt;value&gt;]”<br>“invariants.deformMayFold[&lt;value&gt;]”<br>“animations."&lt;value&gt;"”<br>“&lt;value&gt;.offsets[&lt;value&gt;]”<br>“{stop "&lt;value&gt;" / stops[&lt;value&gt;]}”<br>“&lt;value&gt; properties."&lt;value&gt;".to."&lt;value&gt;"”<br>“this rig spec”<br>“&lt;value&gt;.derive”<br>“setup."&lt;value&gt;"”<br>“physics."&lt;value&gt;"”<br>“&lt;value&gt;'s "lower"”<br>“&lt;value&gt; "sequence"”<br>“&lt;value&gt; generator.bias”<br>“&lt;value&gt; generator.depth”<br>“&lt;value&gt;.events[&lt;value&gt;]”<br>“&lt;value&gt;.tracks[&lt;value&gt;]”<br>“invariants.axes[&lt;value&gt;]”<br>“&lt;value&gt; generator.falloff”<br>“&lt;value&gt;.drawOrder[&lt;value&gt;]”<br>“&lt;value&gt; generator.influence”<br>“invariants.detached[&lt;value&gt;]”<br>“{slot "&lt;value&gt;" / slots[&lt;value&gt;]}”<br>“invariants.consumerDrivenMix[&lt;value&gt;]”<br>“event "&lt;value&gt;"”<br>“&lt;value&gt;'s "from"”<br>“this motion spec”<br>“{absent / &lt;value&gt;}”<br>“{region / &lt;value&gt;}”<br>“&lt;value&gt;.keys[&lt;value&gt;]”<br>“&lt;value&gt; generator.soft”<br>“{linkedmesh / &lt;value&gt;}”<br>“&lt;value&gt;.deform[&lt;value&gt;]”<br>“&lt;value&gt;.sequence[&lt;value&gt;]”<br>“&lt;value&gt; generator (&lt;value&gt;)”<br>“{bone "&lt;value&gt;" / bones[&lt;value&gt;]}”<br>Here the values named in the message include: “uvs”, “mixX”, “blend”, “scaleX”, “groups”, “radius”, “images”, “axisBone”, “maxBones”, “massBone”, “softness”, “timelines”, “archetype”, “rotateMode”, “windGlobal”, “localTarget”, “spacingMode”, “positionMode”, “inertiaGlobal”, “dampingGlobal”, “gravityGlobal”, “strengthGlobal”, “skeleton.stageBox”, “invariants.idleDrivesMeshes”, “ik”, “lag”, “why”, “cut”, “fps”, “icon”, “dark”, “cols”, “kind”, “hull”, “cell”, “path”, “loop”, “mask”, “ease”, “ramp”, “note”, “mode”, “size”, “rows”, “mixY”, “alpha”, “pairs”, “inner”, “curve”, “limit”, “edges”, “float”, “start”, “audio”, “along”, “clamp”, “width”, “skins”, “links”, “chain”, “phase”, “about”, “power”, “count”, “color”, “gamma”, “index”, “delay”, “shearY”, “source”, “convex”, “target”, “amount”, “volume”, “shearX”, “slider”, “string”, “center”, “parent”, “closed”, “zScale”, “inward”, “margin”, “across”, “height”, “digits”, “scaleY”, “anchor”, “degrees”, “inverse”, “stretch”, “easings”, “against”, “default”, “inherit”, “lengths”, “carried”, “balance”, “stagger”, “outward”, “through”, “vertices”, “axis_deg”, “contrast”, “compress”, “notUnder”, “property”, “duration”, “controls”, “additive”, “rotation”, “triangles”, “mixScaleY”, “mixScaleX”, “mixShearY”, “tolerance”, “mixRotate”, “meshSlots”, “minWeight”, “mixGlobal”, “amplitude”, “massGlobal”, “meshCenter”, “fromVertex”, “slotWindow”, “wavelength”, “"skeleton"”, “attachments”, “vertexCount”, “maxVertices”, “localSource”, “"invariants"”, “bendPositive”, “boneIndexing”, “constantSpeed”, “meshTriangles”, “referenceScale”. | Fix each printed stray key's spelling using the suggested or known names, or remove it. |
7475
+ | <a id="CE_KEYS_NUMBER_FLOAT32_FINITE"></a>`CE_KEYS_NUMBER_FLOAT32_FINITE` | “&lt;where&gt;: &lt;place(path)&gt; is &lt;String(node)&gt;; a number in this file is finite at float32 precision, at most ±&lt;String(FLOAT32_MAX)&gt;, because the skeleton is written as float32 — past that it would be emitted as Infinity, which JSON writes as null, a value the file never stated.&lt;why&gt;”<br>“{ / { This one is finite as a double and has no float32 but Infinity. / JSON has no spelling for Infinity: a literal past ±1.7976931348623157e308, such as 1e309, parses to it.}}” | State a finite number whose float32 rounding stays finite; inspect the printed path and magnitude. |
7476
+ | <a id="CE_KEYS_FIELD_VALUE_TYPE"></a>`CE_KEYS_FIELD_VALUE_TYPE` | “&lt;where&gt;: &lt;visit.name([key, ...wrong.tail])&gt; is &lt;typeFound(wrong.value)&gt;; &lt;wrong.required&gt; is required”<br>“a boolean (true or false)”<br>“a number”<br>“a number or null”<br>“a string”<br>“a string or null”<br>“an array of arrays of numbers”<br>“an array of numbers”<br>“an array of numbers, or null”<br>“an array of strings”<br>“an object whose every value is a string or null”<br>“an object whose every value is an array of numbers”<br>“an object whose every value is an array of strings” | Replace the named field or element with the required JSON type printed in the message. |
7477
+ | <a id="CE_KEYS_ENUM_VALUE"></a>`CE_KEYS_ENUM_VALUE` | “&lt;where&gt;: &lt;visit.name([key])&gt; is &lt;JSON.stringify(value) ?? String(value)&gt;; one of &lt;rule.set.map((name) =&gt; JSON.stringify(name)).join(', ')&gt; — &lt;rule.readAs&gt;”<br>“anything else was read as a ribbon by the mesh checks and as a ring by the control-bone reader and the geometry builder, so the refusal it got named a fault the part did not have”<br>“anything else was read as no rotation source, and the bone was emitted without the setup rotation it asked for”<br>“anything else was read as the default "name" in silence: a weighted "vertices" run was refused as unflagged, and every other attachment built byte for byte as if the key were absent” | Choose one of the printed names for the named field; the readAs explanation describes why another spelling changes its meaning. |
7127
7478
 
7128
7479
  ### 5.2 Assertions — the gate
7129
7480