{
 "version": 1,
 "codes": {
  "background_not_drawable_here": {
   "says": "A scene's background is not one of the six this renderer draws, so it would be drawn as another.",
   "fix": "Use one of beach, meadow, classroom, stage, space or city as the place's background, or pass allow_substitutes: true to draw the meadow instead (listed in the result).",
   "url": "https://jabbertoon.com/docs/errors/#background_not_drawable_here",
   "level": "error",
   "example": {
    "program": {
     "v": 1,
     "kind": "cartoon",
     "cast": {
      "A": {
       "name": "Ann",
       "look": {
        "template": "kid"
       }
      }
     },
     "scripts": [
      {
       "hat": {
        "on": "scene",
        "name": "One",
        "place": "kitchen"
       },
       "body": [
        {
         "op": "say",
         "who": "A",
         "text": "Hi!"
        }
       ]
      }
     ]
    },
    "says": "places: A background cannot be drawn here: kitchen (it is not one of the six backgrounds (beach, meadow, classroom, stage, space, city))."
   }
  },
  "bad_arguments": {
   "says": "The call's arguments are not ones the tool can use: one is missing, unknown or of the wrong type.",
   "fix": "Send the arguments the tool's inputSchema gives, as the message says.",
   "url": "https://jabbertoon.com/docs/errors/#bad_arguments",
   "level": "error"
  },
  "bad_fps": {
   "says": "That frame rate is not one this renderer makes.",
   "fix": "Use 24 (the default) or any whole number up to 30. The cartoon itself always runs on its 24 frames-a-second clock.",
   "url": "https://jabbertoon.com/docs/errors/#bad_fps",
   "level": "error"
  },
  "bad_option": {
   "says": "An option has a value this renderer does not take.",
   "fix": "See the option named in the message, and the values it takes.",
   "url": "https://jabbertoon.com/docs/errors/#bad_option",
   "level": "error"
  },
  "bad_size": {
   "says": "That frame size is not one this renderer makes.",
   "fix": "Use 1280x720 (the default), 1920x1080 or 1080x1920 for a video; a frame or a contact sheet takes any size from 16 to 3840 pixels a side.",
   "url": "https://jabbertoon.com/docs/errors/#bad_size",
   "level": "error"
  },
  "bad_time": {
   "says": "That time is not in the cartoon.",
   "fix": "Give a time in seconds from 0 to the cartoon's length.",
   "url": "https://jabbertoon.com/docs/errors/#bad_time",
   "level": "error"
  },
  "block_has_no_body": {
   "says": "A block that holds no body was given one; its body never runs.",
   "fix": "Move the blocks out of it, or into a block that holds a body (for, repeat, forever, while, if, between).",
   "url": "https://jabbertoon.com/docs/errors/#block_has_no_body",
   "patchable": true,
   "level": "warning"
  },
  "block_needs_op": {
   "says": "A block has no \"op\" saying what it is.",
   "fix": "Give each block an \"op\": {\"op\": \"say\", ...}.",
   "url": "https://jabbertoon.com/docs/errors/#block_needs_op",
   "level": "error"
  },
  "blocks_never_run": {
   "says": "The scene ends before a script reaches some of its blocks, so they never run.",
   "fix": "Let the script reach its end before the scene ends: pin the next scene later, or take out the wait the script was held at.",
   "level": "warning",
   "url": "https://jabbertoon.com/docs/errors/#blocks_never_run"
  },
  "body_not_list": {
   "says": "A body is not a list of blocks.",
   "fix": "Make the body a list: \"body\": [{...}, {...}].",
   "url": "https://jabbertoon.com/docs/errors/#body_not_list",
   "level": "error"
  },
  "branches_not_list": {
   "says": "The branches of an at-the-same-time block are not a list of bodies.",
   "fix": "Write branches as a list of lists of blocks: [[...], [...]].",
   "url": "https://jabbertoon.com/docs/errors/#branches_not_list",
   "level": "error"
  },
  "busy": {
   "says": "The online tools are busy: they have answered all they take today, or as many at once as they take.",
   "fix": "Try again after the time Retry-After gives; the studio at https://jabbertoon.com/studio/ and the tool on your own computer work without them.",
   "url": "https://jabbertoon.com/docs/errors/#busy",
   "level": "error"
  },
  "canvas_unavailable": {
   "says": "There is no canvas to draw on here.",
   "fix": "Install the package again (npm install); its canvas library (@napi-rs/canvas) has builds for Windows, macOS and Linux on Node 22 or later.",
   "url": "https://jabbertoon.com/docs/errors/#canvas_unavailable",
   "level": "error"
  },
  "caption_cut": {
   "says": "A caption is cut off before its time is up, when its scene ends.",
   "fix": "A caption does not wait: put a wait after it (as long as its for), or end the scene later.",
   "level": "warning",
   "url": "https://jabbertoon.com/docs/errors/#caption_cut"
  },
  "caption_hidden": {
   "says": "A line said while a caption is up takes its place, so the caption is hidden for most of its time.",
   "fix": "A line takes the place of a caption while it is said: give the caption its own moment, before or after the line.",
   "level": "warning",
   "url": "https://jabbertoon.com/docs/errors/#caption_hidden"
  },
  "caption_needs_text": {
   "says": "A caption has no words.",
   "fix": "Give the caption as text: \"text\": \"Later that day\".",
   "url": "https://jabbertoon.com/docs/errors/#caption_needs_text",
   "level": "error"
  },
  "caption_too_long": {
   "says": "A caption (or a line, which shows as one) takes more than about three lines of the picture.",
   "fix": "Split the words into two captions (or lines), each of at most about three lines.",
   "url": "https://jabbertoon.com/docs/errors/#caption_too_long",
   "level": "warning"
  },
  "cartoon_empty": {
   "says": "The cartoon has no scenes, so there is nothing to play, and render_video and preview refuse it.",
   "fix": "Add a scene: {\"hat\": {\"on\": \"scene\", \"name\": \"Hello\"}, \"body\": [{\"op\": \"say\", \"who\": \"dog\", \"text\": \"Hi!\"}]}.",
   "url": "https://jabbertoon.com/docs/errors/#cartoon_empty",
   "level": "error",
   "example": {
    "program": {
     "v": 1,
     "kind": "cartoon",
     "cast": {
      "A": {
       "name": "Ann",
       "look": {
        "template": "kid"
       }
      }
     },
     "scripts": []
    },
    "says": "scripts: has no scenes, so there is nothing to play"
   }
  },
  "cartoon_fails_when_played": {
   "says": "The cartoon stopped with an error while it was being played, so it was not drawn.",
   "fix": "Fix what the message names, as validate's play check does (fails_when_played, at the same time): a name in a formula that is not a setting, a variable or one the engine has; a character (who) that is not in the cast; or a loop that never waits (put a wait in it).",
   "url": "https://jabbertoon.com/docs/errors/#cartoon_fails_when_played",
   "level": "error",
   "example": {
    "program": {
     "v": 1,
     "kind": "cartoon",
     "cast": {
      "A": {
       "name": "Ann",
       "look": {
        "template": "kid"
       }
      }
     },
     "scripts": [
      {
       "hat": {
        "on": "scene",
        "name": "One"
       },
       "body": [
        {
         "op": "wait",
         "s": "=nope + 1"
        }
       ]
      }
     ]
    },
    "says": "The cartoon stopped with an error before its first frame: expression: unknown name \"nope\""
   }
  },
  "cartoon_file_field_unknown": {
   "says": "A cartoon file holds its cast, its places and its program, and nothing else.",
   "fix": "Move the field into the program where it belongs, or leave it out.",
   "url": "https://jabbertoon.com/docs/errors/#cartoon_file_field_unknown",
   "level": "error",
   "example": {
    "program": {
     "pack": 1,
     "id": "c4c:cartoon:happy_now",
     "type": "cartoon",
     "version": "1.0.1",
     "name": "Happy now?",
     "description": "Sunny brings Grump a cake with sprinkles. Two characters, two scenes, about 23 seconds.",
     "author": {
      "id": "you",
      "name": "You"
     },
     "license": "cc0",
     "remixable": true,
     "derived_from": [],
     "preview": {
      "seconds": 23
     },
     "content_hash": "sha256:28ac64431d1fac33415608eb770bb63fd22de03c84953fe5369bec79925cc505",
     "content": {
      "cast": {
       "A": {
        "name": "Sunny",
        "legs": 2,
        "look": {
         "template": "person",
         "colors": {
          "body": "#ffcf77",
          "acc": "#6a4c93"
         }
        }
       },
       "B": {
        "name": "Grump",
        "legs": 4,
        "at": {
         "x": 0.68,
         "y": 0.92,
         "h": 0.34,
         "facing": -1
        },
        "look": {
         "template": "dog",
         "colors": {
          "skin": "#9e8a78",
          "body": "#d9cbbd",
          "acc": "#5a4636"
         }
        }
       }
      },
      "places": {
       "park": {
        "background": "meadow"
       }
      },
      "program": {
       "v": 1,
       "kind": "cartoon",
       "name": "Happy now?",
       "scripts": [
        {
         "hat": {
          "on": "scene",
          "name": "Morning",
          "place": "park"
         },
         "body": [
          {
           "op": "does",
           "who": "B",
           "behaviour": "c4c:beh:sadidle"
          },
          {
           "op": "caption",
           "text": "Grump was having a grey sort of morning.",
           "for": 2.6
          },
          {
           "op": "wait",
           "s": 1.2
          },
          {
           "op": "does",
           "who": "A",
           "behaviour": "c4c:beh:walk",
           "for": 2,
           "params": {
            "from": 0,
            "to": 0,
            "t_in": 2
           }
          },
          {
           "op": "enter",
           "who": "A",
           "from": "left",
           "over": 2,
           "x": 0.3
          },
          {
           "op": "does",
           "who": "A",
           "behaviour": "c4c:beh:wave_hello"
          },
          {
           "op": "say",
           "who": "A",
           "text": "Good morning, Grump!",
           "mood": "happy"
          },
          {
           "op": "does",
           "who": "B",
           "behaviour": "c4c:beh:annoyed"
          },
          {
           "op": "say",
           "who": "B",
           "text": "Is it?",
           "mood": "angry"
          },
          {
           "op": "wait",
           "s": 0.5
          },
          {
           "op": "does",
           "who": "A",
           "behaviour": "c4c:beh:bounce"
          },
          {
           "op": "say",
           "who": "A",
           "text": "I baked you a cake. It has sprinkles!",
           "mood": "happy"
          },
          {
           "op": "does",
           "who": "B",
           "behaviour": "c4c:beh:sadidle"
          },
          {
           "op": "say",
           "who": "B",
           "text": "I don't like sprinkles.",
           "mood": "sad"
          },
          {
           "op": "wait",
           "s": 0.8
          }
         ]
        },
        {
         "hat": {
          "on": "scene",
          "name": "One bite later"
         },
         "body": [
          {
           "op": "caption",
           "text": "One bite later...",
           "for": 1.6
          },
          {
           "op": "does",
           "who": "B",
           "behaviour": "c4c:beh:idle"
          },
          {
           "op": "does",
           "who": "A",
           "behaviour": "c4c:beh:point"
          },
          {
           "op": "wait",
           "s": 1
          },
          {
           "op": "say",
           "who": "A",
           "text": "Are you happy now?",
           "mood": "happy"
          },
          {
           "op": "wait",
           "s": 0.9
          },
          {
           "op": "does",
           "who": "B",
           "behaviour": "c4c:beh:wag"
          },
          {
           "op": "say",
           "who": "B",
           "text": "...Maybe a little."
          },
          {
           "op": "cut",
           "place": "park",
           "mood": "bloom"
          },
          {
           "op": "does",
           "who": "A",
           "behaviour": "c4c:beh:jump_for_joy"
          },
          {
           "op": "say",
           "who": "A",
           "text": "Hooray! Cake for everyone!",
           "mood": "happy"
          },
          {
           "op": "say",
           "who": "B",
           "text": "Don't make it weird.",
           "mood": "angry"
          },
          {
           "op": "does",
           "who": "A",
           "behaviour": "c4c:beh:walk",
           "for": 2.4,
           "params": {
            "from": 0,
            "to": 0,
            "t_in": 2.4
           }
          },
          {
           "op": "together",
           "branches": [
            [
             {
              "op": "exit",
              "who": "A",
              "to": "left",
              "over": 2.4
             }
            ],
            [
             {
              "op": "wait",
              "s": 1.2
             },
             {
              "op": "say",
              "who": "B",
              "text": "Thanks for the cake.",
              "speed": 0.85
             }
            ]
           ]
          },
          {
           "op": "mood",
           "who": "B",
           "mood": "happy"
          },
          {
           "op": "wait",
           "s": 1.2
          }
         ]
        }
       ]
      },
      "extra": 1
     }
    },
    "says": "content.extra: a cartoon pack holds {cast, places, program} only"
   }
  },
  "cartoon_file_no_program": {
   "says": "A cartoon file needs its program.",
   "fix": "Give {\"cast\": {...}, \"program\": {\"v\": 1, \"kind\": \"cartoon\", \"scripts\": [...]}}.",
   "url": "https://jabbertoon.com/docs/errors/#cartoon_file_no_program",
   "level": "error",
   "example": {
    "program": {
     "format": "jabbertoon-project",
     "version": 2,
     "cartoon": 5,
     "assets": {
      "characters": {},
      "sounds": {}
     }
    },
    "says": "cartoon: a project file holds its cartoon in \"cartoon\""
   }
  },
  "cartoon_over_limit": {
   "says": "The cartoon is longer than 600 seconds (or never ends), so it was not drawn.",
   "fix": "Make it 10 minutes or shorter: end every scene (a \"forever\" loop needs a scene that ends it), or split it into parts.",
   "url": "https://jabbertoon.com/docs/errors/#cartoon_over_limit",
   "level": "error",
   "example": {
    "program": {
     "v": 1,
     "kind": "cartoon",
     "cast": {
      "A": {
       "name": "Ann",
       "look": {
        "template": "kid"
       }
      }
     },
     "scripts": [
      {
       "hat": {
        "on": "scene",
        "name": "One"
       },
       "body": [
        {
         "op": "wait",
         "s": 700
        }
       ]
      }
     ]
    },
    "says": "The cartoon is still playing after 601 seconds (it is longer than the limit of 600 seconds, or a scene never ends), so it was not drawn."
   }
  },
  "cartoon_script_needs_scene_hat": {
   "says": "A cartoon script does not start with a scene hat that has a name.",
   "fix": "Start every script of a cartoon with {\"on\": \"scene\", \"name\": \"...\"}.",
   "url": "https://jabbertoon.com/docs/errors/#cartoon_script_needs_scene_hat",
   "level": "error"
  },
  "cast_at_field_unknown": {
   "says": "A cast member's \"at\" has a field other than x, y, h and facing; it is ignored.",
   "fix": "Keep only x, y, h and facing in \"at\".",
   "url": "https://jabbertoon.com/docs/errors/#cast_at_field_unknown",
   "suggest_from": "fields",
   "patchable": true,
   "level": "warning"
  },
  "cast_at_not_number": {
   "says": "A value of a cast member's \"at\" is not a number.",
   "fix": "Give x, y, h and facing as numbers (a formula is not allowed there): x from 0 to 1, y the feet line (the ground is 0.92), h a share of the stage's height.",
   "url": "https://jabbertoon.com/docs/errors/#cast_at_not_number",
   "level": "error"
  },
  "cast_at_not_object": {
   "says": "A cast member's \"at\" is not {x, y, h, facing}.",
   "fix": "Write where it stands as {\"x\": 0.3, \"y\": 0.92, \"h\": 0.5, \"facing\": 1} (stage fractions; facing 1 right, -1 left).",
   "url": "https://jabbertoon.com/docs/errors/#cast_at_not_object",
   "level": "error"
  },
  "cast_entry_bad": {
   "says": "A cast member is neither a role description (text) nor an object.",
   "fix": "Write the member as {\"name\", \"legs\", \"at\", \"voice\", \"pack\", \"look\"}, or as text describing its role.",
   "url": "https://jabbertoon.com/docs/errors/#cast_entry_bad",
   "level": "error"
  },
  "cast_field_unknown": {
   "says": "A cast member has a field the language does not use; it is ignored.",
   "fix": "Remove the field, or move it where it belongs (colours go in look.colors, the template in look.template).",
   "url": "https://jabbertoon.com/docs/errors/#cast_field_unknown",
   "suggest_from": "fields",
   "patchable": true,
   "level": "warning"
  },
  "cast_has_no_design": {
   "says": "A cast member is only a role (a few words), with no look, pack or picture to draw, so render_video refuses it.",
   "fix": "Give it a look with one of the six characters as its template, keeping its words as its name: {\"name\": \"Biscuit\", \"look\": {\"template\": \"dog\"}}.",
   "url": "https://jabbertoon.com/docs/errors/#cast_has_no_design",
   "level": "error",
   "example": {
    "program": {
     "v": 1,
     "kind": "cartoon",
     "cast": {
      "A": "a friendly dog"
     },
     "scripts": [
      {
       "hat": {
        "on": "scene",
        "name": "One"
       },
       "body": [
        {
         "op": "say",
         "who": "A",
         "text": "Hi!"
        }
       ]
      }
     ]
    },
    "says": "cast.A: is only a role (\"a friendly dog\"): it has no look, pack or picture to draw, so render_video refuses it"
   }
  },
  "cast_id_bad": {
   "says": "A cast id has a letter it cannot have.",
   "fix": "Use letters, digits, _ or - in a cast id (A, sunny, dog_2), and the same id in every \"who\".",
   "url": "https://jabbertoon.com/docs/errors/#cast_id_bad",
   "level": "error"
  },
  "cast_is_a_list": {
   "says": "The cast is a list, so its members are named \"0\", \"1\", ... and each who must say one of those.",
   "fix": "Write the cast as an object keyed by the ids the who fields use: {\"dog\": {\"name\": \"Biscuit\"}, \"cat\": {\"name\": \"Mia\"}}.",
   "url": "https://jabbertoon.com/docs/errors/#cast_is_a_list",
   "level": "warning",
   "example": {
    "program": {
     "cast": [
      {
       "name": "Ann",
       "look": {
        "template": "kid"
       }
      }
     ],
     "program": {
      "v": 1,
      "kind": "cartoon",
      "scripts": [
       {
        "hat": {
         "on": "scene",
         "name": "One"
        },
        "body": [
         {
          "op": "say",
          "who": "0",
          "text": "Hi!"
         }
        ]
       }
      ]
     }
    },
    "says": "cast: is a list, so its entries are named \"0\", \"1\", ... and each \"who\" must say one of those"
   }
  },
  "cast_legs_bad": {
   "says": "A cast member's legs is not a whole number.",
   "fix": "Give legs as 0, 2 or 4 (a whole number, 0 or more).",
   "url": "https://jabbertoon.com/docs/errors/#cast_legs_bad",
   "level": "error"
  },
  "cast_missing": {
   "says": "The scene has no cast, so every \"who\" must name a character the page adds itself.",
   "fix": "Add a cast: {\"A\": {\"name\": \"Sunny\"}}, and use its ids in \"who\".",
   "url": "https://jabbertoon.com/docs/errors/#cast_missing",
   "level": "warning"
  },
  "cast_name_not_text": {
   "says": "A cast member's name is not text.",
   "fix": "Give the name as text in quotes: \"name\": \"Sunny\".",
   "url": "https://jabbertoon.com/docs/errors/#cast_name_not_text",
   "level": "error"
  },
  "cast_not_drawable_here": {
   "says": "A character in the cast cannot be drawn here: it is a picture from the internet, a role with no design, a character pack this renderer does not have, or a design it does not know.",
   "fix": "Give the character a look ({\"template\": \"dog\", \"style\": \"outlined\"}) or one of the shipped character packs (c4c:char:person, kid, dog, cat, bird, monster), or a picture of its own in a project file; or pass allow_substitutes: true to draw a stand-in, listed in the result.",
   "url": "https://jabbertoon.com/docs/errors/#cast_not_drawable_here",
   "level": "error",
   "example": {
    "program": {
     "v": 1,
     "kind": "cartoon",
     "cast": {
      "A": {
       "name": "Ann",
       "look": {
        "template": "kid",
        "image": "https://example.com/ann.png"
       }
      }
     },
     "scripts": [
      {
       "hat": {
        "on": "scene",
        "name": "One"
       },
       "body": [
        {
         "op": "say",
         "who": "A",
         "text": "Hi!"
        }
       ]
      }
     ]
    },
    "says": "cast.A: Character A (Ann) cannot be drawn here: a picture from outside (image) (pictures from the internet (emoji, Open Peeps, DiceBear) are never fetched by the renderer)."
   }
  },
  "cast_not_object": {
   "says": "The cast is not an object of members by id.",
   "fix": "Write the cast as {\"A\": {\"name\": \"Sunny\"}, \"B\": {...}}: one entry per character, keyed by its id.",
   "url": "https://jabbertoon.com/docs/errors/#cast_not_object",
   "level": "error"
  },
  "cast_over_studio_limit": {
   "says": "The cast has more characters than the studio opens.",
   "fix": "Keep the cast to two characters to open the cartoon in the studio; a longer cast still validates and plays.",
   "url": "https://jabbertoon.com/docs/errors/#cast_over_studio_limit",
   "level": "warning"
  },
  "cast_pack_bad": {
   "says": "A cast member's pack is neither an id nor {id, version}.",
   "fix": "Give the pack as \"c4c:char:dog\" or {\"id\": \"c4c:char:dog\", \"version\": \"1.0.0\"}.",
   "url": "https://jabbertoon.com/docs/errors/#cast_pack_bad",
   "level": "error"
  },
  "cast_pack_id_bad": {
   "says": "A cast member's pack is not a pack id.",
   "fix": "Give the pack id as written in the pack, like \"c4c:char:dog\".",
   "url": "https://jabbertoon.com/docs/errors/#cast_pack_id_bad",
   "level": "error"
  },
  "cast_pack_version_not_text": {
   "says": "A cast member's pack version is not text.",
   "fix": "Give the version as text, like \"1.0.0\", or leave it out.",
   "url": "https://jabbertoon.com/docs/errors/#cast_pack_version_not_text",
   "level": "error"
  },
  "cast_voice_not_text": {
   "says": "A cast member's voice is not text.",
   "fix": "Give the voice as text, one of the studio's voices such as \"af_heart\".",
   "url": "https://jabbertoon.com/docs/errors/#cast_voice_not_text",
   "suggest_from": "voices",
   "level": "error"
  },
  "chain_channel_bad": {
   "says": "A chain wave runs down something that is not one part.",
   "fix": "Give a part channel without a #number, like \"part:tail\".",
   "url": "https://jabbertoon.com/docs/errors/#chain_channel_bad",
   "level": "error"
  },
  "chain_needs_channel": {
   "says": "A chain wave does not say which part it runs down.",
   "fix": "Give \"ch\", the part, like \"part:tail\".",
   "url": "https://jabbertoon.com/docs/errors/#chain_needs_channel",
   "level": "error"
  },
  "chain_not_a_chain": {
   "says": "A chain wave runs down a part that is drawn in one piece, so only its first segment moves.",
   "fix": "Run the chain down a tail, the body, the ears or the hair, or use a wave on the part.",
   "url": "https://jabbertoon.com/docs/errors/#chain_not_a_chain",
   "level": "warning"
  },
  "chain_on_legs": {
   "says": "A chain wave on legs runs from leg to leg (a leg's #number says which leg), not down one leg.",
   "fix": "Run the chain down a tail, the body, the ears or the hair; move legs with their own blocks.",
   "url": "https://jabbertoon.com/docs/errors/#chain_on_legs",
   "level": "warning"
  },
  "chain_part_is_a_raise": {
   "says": "A block that turns a part was given a raise (lift:).",
   "fix": "Name the part itself (\"tail\"), not its raise.",
   "url": "https://jabbertoon.com/docs/errors/#chain_part_is_a_raise",
   "level": "error"
  },
  "chain_part_segment": {
   "says": "A chain block was given one segment of a chain; it numbers the segments itself.",
   "fix": "Name the whole part (\"tail\"), not \"part:tail#2\".",
   "url": "https://jabbertoon.com/docs/errors/#chain_part_segment",
   "level": "error"
  },
  "channel_bad": {
   "says": "A channel is not one the language has.",
   "fix": "Use dx, dy, rot, sx, sy, mouth, blink, or part:<part> or lift:<part>, like part:arm:-1 (the left arm).",
   "url": "https://jabbertoon.com/docs/errors/#channel_bad",
   "level": "error"
  },
  "channel_values_not_object": {
   "says": "A set or glide's channels are not {channel: value}.",
   "fix": "Write them as {\"dx\": 40, \"part:arm:1\": 30}.",
   "url": "https://jabbertoon.com/docs/errors/#channel_values_not_object",
   "level": "error"
  },
  "character_invalid": {
   "says": "A part, a shape or the face of the character is not one the studio can draw.",
   "fix": "Fix the part named, as its fix says (the character format: https://jabbertoon.com/docs/packs/).",
   "url": "https://jabbertoon.com/docs/errors/#character_invalid",
   "level": "error",
   "example": {
    "program": {
     "name": "Rex",
     "content": {
      "tree": 5,
      "legs": 4,
      "kind": "dog",
      "height": 178.4,
      "footprint": 120,
      "look": "outlined",
      "views": [
       {
        "view": "side"
       },
       {
        "view": "front",
        "tree": {
         "id": "root",
         "role": "root",
         "pos": {
          "x": 0,
          "y": 0
         },
         "rot": 0,
         "sx": 1,
         "sy": 1,
         "z": 0,
         "children": [
          {
           "id": "torso",
           "role": "torso",
           "shape": {
            "type": "ellipse",
            "w": 87.5,
            "h": 77
           },
           "pos": {
            "x": 0,
            "y": -91
           },
           "rot": 0,
           "sx": 1,
           "sy": 1,
           "z": 0,
           "fill": "#b8793f",
           "children": [
            {
             "id": "bib",
             "role": null,
             "shape": {
              "type": "ellipse",
              "w": 43.4,
              "h": 43.4
             },
             "pos": {
              "x": 0,
              "y": 7
             },
             "rot": 0,
             "sx": 1,
             "sy": 1,
             "z": 0,
             "fill": "#f7d9b0",
             "children": []
            },
            {
             "id": "tail",
             "role": "tail",
             "index": 0,
             "shape": {
              "type": "taper",
              "w": 18,
              "w2": 11,
              "h": 59.5
             },
             "pos": {
              "x": 15.4,
              "y": -15.4
             },
             "rot": 196,
             "sx": 1,
             "sy": 1,
             "z": -3,
             "fill": "#b8793f",
             "children": [
              {
               "id": "tail1",
               "role": "tail",
               "index": 1,
               "pos": {
                "x": 0,
                "y": 14.875
               },
               "rot": 0,
               "sx": 1,
               "sy": 1,
               "z": 0,
               "children": [
                {
                 "id": "tail2",
                 "role": "tail",
                 "index": 2,
                 "pos": {
                  "x": 0,
                  "y": 14.875
                 },
                 "rot": 0,
                 "sx": 1,
                 "sy": 1,
                 "z": 0,
                 "children": [
                  {
                   "id": "tail3",
                   "role": "tail",
                   "index": 3,
                   "pos": {
                    "x": 0,
                    "y": 14.875
                   },
                   "rot": 0,
                   "sx": 1,
                   "sy": 1,
                   "z": 0,
                   "children": [],
                   "limits": {
                    "min": -70,
                    "max": 70
                   },
                   "tip": {
                    "x": 0,
                    "y": 14.875
                   }
                  }
                 ],
                 "limits": {
                  "min": -70,
                  "max": 70
                 }
                }
               ],
               "limits": {
                "min": -70,
                "max": 70
               }
              }
             ],
             "limits": {
              "min": -120,
              "max": 120
             },
             "bend": true
            },
            {
             "id": "leg0",
             "role": "leg",
             "side": -1,
             "index": 0,
             "shape": {
              "type": "capsule",
              "w": 21,
              "h": 35.42
             },
             "pos": {
              "x": -28,
              "y": 9.8
             },
             "rot": 0,
             "sx": 1,
             "sy": 1,
             "z": -2,
             "fill": "#a26a37",
             "children": [
              {
               "id": "low0",
               "role": "shin",
               "side": -1,
               "index": 0,
               "shape": {
                "type": "capsule",
                "w": 18,
                "h": 32.2
               },
               "pos": {
                "x": 0,
                "y": 32.2
               },
               "rot": 0,
               "sx": 1,
               "sy": 1,
               "z": 0,
               "fill": "#a26a37",
               "children": [
                {
                 "id": "paw0",
                 "role": "foot",
                 "side": -1,
                 "index": 0,
                 "shape": {
                  "type": "hcapsule",
                  "w": 26,
                  "h": 15
                 },
                 "pos": {
                  "x": 0,
                  "y": 32.268
                 },
                 "rot": 0,
                 "sx": 1,
                 "sy": 1,
                 "z": 0,
                 "fill": "#6b4120",
                 "children": [],
                 "limits": {
                  "min": -45,
                  "max": 45
                 }
                }
               ],
               "limits": {
                "min": -60,
                "max": 60
               },
               "flex": 1,
               "fold": true
              }
             ],
             "limits": {
              "min": -75,
              "max": 60
             },
             "fold": true
            },
            {
             "id": "leg1",
             "role": "leg",
             "side": 1,
             "index": 1,
             "shape": {
              "type": "capsule",
              "w": 21,
              "h": 35.42
             },
             "pos": {
              "x": 28,
              "y": 9.8
             },
             "rot": 0,
             "sx": 1,
             "sy": 1,
             "z": -2,
             "fill": "#a26a37",
             "children": [
              {
               "id": "low1",
               "role": "shin",
               "side": 1,
               "index": 1,
               "shape": {
                "type": "capsule",
                "w": 18,
                "h": 32.2
               },
               "pos": {
                "x": 0,
                "y": 32.2
               },
               "rot": 0,
               "sx": 1,
               "sy": 1,
               "z": 0,
               "fill": "#a26a37",
               "children": [
                {
                 "id": "paw1",
                 "role": "foot",
                 "side": 1,
                 "index": 1,
                 "shape": {
                  "type": "hcapsule",
                  "w": 26,
                  "h": 15
                 },
                 "pos": {
                  "x": 0,
                  "y": 32.268
                 },
                 "rot": 0,
                 "sx": 1,
                 "sy": 1,
                 "z": 0,
                 "fill": "#6b4120",
                 "children": [],
                 "limits": {
                  "min": -45,
                  "max": 45
                 }
                }
               ],
               "limits": {
                "min": -60,
                "max": 60
               },
               "flex": -1,
               "fold": true
              }
             ],
             "limits": {
              "min": -60,
              "max": 75
             },
             "fold": true
            },
            {
             "id": "leg2",
             "role": "leg",
             "side": -1,
             "index": 2,
             "shape": {
              "type": "capsule",
              "w": 21,
              "h": 38.5
             },
             "pos": {
              "x": -17.5,
              "y": 15.4
             },
             "rot": 0,
             "sx": 1,
             "sy": 1,
             "z": 1,
             "fill": "#b8793f",
             "children": [
              {
               "id": "low2",
               "role": "shin",
               "side": -1,
               "index": 2,
               "shape": {
                "type": "capsule",
                "w": 18,
                "h": 35
               },
               "pos": {
                "x": 0,
                "y": 35
               },
               "rot": 0,
               "sx": 1,
               "sy": 1,
               "z": 0,
               "fill": "#b8793f",
               "children": [
                {
                 "id": "paw2",
                 "role": "foot",
                 "side": -1,
                 "index": 2,
                 "shape": {
                  "type": "hcapsule",
                  "w": 26,
                  "h": 15
                 },
                 "pos": {
                  "x": 0,
                  "y": 32.9
                 },
                 "rot": 0,
                 "sx": 1,
                 "sy": 1,
                 "z": 0,
                 "fill": "#7a4a24",
                 "children": [],
                 "limits": {
                  "min": -45,
                  "max": 45
                 }
                }
               ],
               "limits": {
                "min": -60,
                "max": 60
               },
               "flex": 1,
               "fold": true
              }
             ],
             "limits": {
              "min": -75,
              "max": 60
             },
             "fold": true
            },
            {
             "id": "leg3",
             "role": "leg",
             "side": 1,
             "index": 3,
             "shape": {
              "type": "capsule",
              "w": 21,
              "h": 38.5
             },
             "pos": {
              "x": 17.5,
              "y": 15.4
             },
             "rot": 0,
             "sx": 1,
             "sy": 1,
             "z": 1,
             "fill": "#b8793f",
             "children": [
              {
               "id": "low3",
               "role": "shin",
               "side": 1,
               "index": 3,
               "shape": {
                "type": "capsule",
                "w": 18,
                "h": 35
               },
               "pos": {
                "x": 0,
                "y": 35
               },
               "rot": 0,
               "sx": 1,
               "sy": 1,
               "z": 0,
               "fill": "#b8793f",
               "children": [
                {
                 "id": "paw3",
                 "role": "foot",
                 "side": 1,
                 "index": 3,
                 "shape": {
                  "type": "hcapsule",
                  "w": 26,
                  "h": 15
                 },
                 "pos": {
                  "x": 0,
                  "y": 32.9
                 },
                 "rot": 0,
                 "sx": 1,
                 "sy": 1,
                 "z": 0,
                 "fill": "#7a4a24",
                 "children": [],
                 "limits": {
                  "min": -45,
                  "max": 45
                 }
                }
               ],
               "limits": {
                "min": -60,
                "max": 60
               },
               "flex": -1,
               "fold": true
              }
             ],
             "limits": {
              "min": -60,
              "max": 75
             },
             "fold": true
            },
            {
             "id": "head",
             "role": "head",
             "shape": {
              "type": "ellipse",
              "w": 76.96000000000001,
              "h": 66.56,
              "oy": -19.2
             },
             "pos": {
              "x": 0,
              "y": -29.4
             },
             "rot": 0,
             "sx": 1,
             "sy": 1,
             "z": 2,
             "fill": "#b8793f",
             "face": {
              "eyeX": 14.8,
              "eyeY": -28.16,
              "eyeR": 7.77,
              "brows": true,
              "mouthW": 22.2,
              "mouthH": 10.88,
              "mouthY": 3.2,
              "z": 1.5
             },
             "children": [
              {
               "id": "snout",
               "role": "snout",
               "shape": {
                "type": "ellipse",
                "w": 38.480000000000004,
                "h": 24.32
               },
               "pos": {
                "x": 0,
                "y": -4.48
               },
               "rot": 0,
               "sx": 1,
               "sy": 1,
               "z": 1,
               "fill": "#f7d9b0",
               "children": [],
               "limits": {
                "min": -20,
                "max": 20
               }
              },
              {
               "id": "nose",
               "role": "nose",
               "shape": {
                "type": "ellipse",
                "w": 14.8,
                "h": 9.6
               },
               "pos": {
                "x": 0,
                "y": -10.88
               },
               "rot": 0,
               "sx": 1,
               "sy": 1,
               "z": 3,
               "fill": "#222",
               "outline": false,
               "children": [],
               "limits": {
                "min": -20,
                "max": 20
               }
              },
              {
               "id": "ear-1",
               "role": "ear",
               "side": -1,
               "index": 0,
               "shape": {
                "type": "teardrop",
                "w": 23.68,
                "h": 49.92
               },
               "pos": {
                "x": -32.56,
                "y": -39.68
               },
               "rot": 26,
               "sx": 1,
               "sy": 1,
               "z": -1,
               "fill": "#7a4a24",
               "children": [
                {
                 "id": "ear-1_1",
                 "role": "ear",
                 "side": -1,
                 "index": 1,
                 "pos": {
                  "x": 0,
                  "y": 24.96
                 },
                 "rot": 0,
                 "sx": 1,
                 "sy": 1,
                 "z": 0,
                 "children": [],
                 "limits": {
                  "min": -60,
                  "max": 60
                 },
                 "tip": {
                  "x": 0,
                  "y": 24.96
                 }
                }
               ],
               "limits": {
                "min": -90,
                "max": 90
               },
               "bend": true
              },
              {
               "id": "ear1",
               "role": "ear",
               "side": 1,
               "index": 0,
               "shape": {
                "type": "teardrop",
                "w": 23.68,
                "h": 49.92
               },
               "pos": {
                "x": 32.56,
                "y": -39.68
               },
               "rot": -26,
               "sx": 1,
               "sy": 1,
               "z": -1,
               "fill": "#7a4a24",
               "children": [
                {
                 "id": "ear1_1",
                 "role": "ear",
                 "side": 1,
                 "index": 1,
                 "pos": {
                  "x": 0,
                  "y": 24.96
                 },
                 "rot": 0,
                 "sx": 1,
                 "sy": 1,
                 "z": 0,
                 "children": [],
                 "limits": {
                  "min": -60,
                  "max": 60
                 },
                 "tip": {
                  "x": 0,
                  "y": 24.96
                 }
                }
               ],
               "limits": {
                "min": -90,
                "max": 90
               },
               "bend": true
              }
             ],
             "limits": {
              "min": -40,
              "max": 40
             }
            }
           ],
           "limits": {
            "min": -30,
            "max": 30
           }
          }
         ]
        },
        "footprint": 64
       },
       {
        "view": "back",
        "tree": {
         "id": "root",
         "role": "root",
         "pos": {
          "x": 0,
          "y": 0
         },
         "rot": 0,
         "sx": -1,
         "sy": 1,
         "z": 0,
         "children": [
          {
           "id": "torso",
           "role": "torso",
           "shape": {
            "type": "ellipse",
            "w": 87.5,
            "h": 77
           },
           "pos": {
            "x": 0,
            "y": -91
           },
           "rot": 0,
           "sx": 1,
           "sy": 1,
           "z": 0,
           "fill": "#b8793f",
           "children": [
            {
             "id": "tail",
             "role": "tail",
             "index": 0,
             "shape": {
              "type": "taper",
              "w": 18,
              "w2": 11,
              "h": 59.5
             },
             "pos": {
              "x": 15.4,
              "y": -15.4
             },
             "rot": 196,
             "sx": 1,
             "sy": 1,
             "z": 3,
             "fill": "#b8793f",
             "children": [
              {
               "id": "tail1",
               "role": "tail",
               "index": 1,
               "pos": {
                "x": 0,
                "y": 14.875
               },
               "rot": 0,
               "sx": 1,
               "sy": 1,
               "z": 0,
               "children": [
                {
                 "id": "tail2",
                 "role": "tail",
                 "index": 2,
                 "pos": {
                  "x": 0,
                  "y": 14.875
                 },
                 "rot": 0,
                 "sx": 1,
                 "sy": 1,
                 "z": 0,
                 "children": [
                  {
                   "id": "tail3",
                   "role": "tail",
                   "index": 3,
                   "pos": {
                    "x": 0,
                    "y": 14.875
                   },
                   "rot": 0,
                   "sx": 1,
                   "sy": 1,
                   "z": 0,
                   "children": [],
                   "limits": {
                    "min": -70,
                    "max": 70
                   },
                   "tip": {
                    "x": 0,
                    "y": 14.875
                   }
                  }
                 ],
                 "limits": {
                  "min": -70,
                  "max": 70
                 }
                }
               ],
               "limits": {
                "min": -70,
                "max": 70
               }
              }
             ],
             "limits": {
              "min": -120,
              "max": 120
             },
             "bend": true
            },
            {
             "id": "leg0",
             "role": "leg",
             "side": -1,
             "index": 0,
             "shape": {
              "type": "capsule",
              "w": 21,
              "h": 38.5
             },
             "pos": {
              "x": -17.5,
              "y": 15.4
             },
             "rot": 0,
             "sx": 1,
             "sy": 1,
             "z": 1,
             "fill": "#b8793f",
             "children": [
              {
               "id": "low0",
               "role": "shin",
               "side": -1,
               "index": 0,
               "shape": {
                "type": "capsule",
                "w": 18,
                "h": 35
               },
               "pos": {
                "x": 0,
                "y": 35
               },
               "rot": 0,
               "sx": 1,
               "sy": 1,
               "z": 0,
               "fill": "#b8793f",
               "children": [
                {
                 "id": "paw0",
                 "role": "foot",
                 "side": -1,
                 "index": 0,
                 "shape": {
                  "type": "hcapsule",
                  "w": 26,
                  "h": 15
                 },
                 "pos": {
                  "x": 0,
                  "y": 32.9
                 },
                 "rot": 0,
                 "sx": 1,
                 "sy": 1,
                 "z": 0,
                 "fill": "#7a4a24",
                 "children": [],
                 "limits": {
                  "min": -45,
                  "max": 45
                 }
                }
               ],
               "limits": {
                "min": -60,
                "max": 60
               },
               "flex": 1,
               "fold": true
              }
             ],
             "limits": {
              "min": -75,
              "max": 60
             },
             "fold": true
            },
            {
             "id": "leg1",
             "role": "leg",
             "side": 1,
             "index": 1,
             "shape": {
              "type": "capsule",
              "w": 21,
              "h": 38.5
             },
             "pos": {
              "x": 17.5,
              "y": 15.4
             },
             "rot": 0,
             "sx": 1,
             "sy": 1,
             "z": 1,
             "fill": "#b8793f",
             "children": [
              {
               "id": "low1",
               "role": "shin",
               "side": 1,
               "index": 1,
               "shape": {
                "type": "capsule",
                "w": 18,
                "h": 35
               },
               "pos": {
                "x": 0,
                "y": 35
               },
               "rot": 0,
               "sx": 1,
               "sy": 1,
               "z": 0,
               "fill": "#b8793f",
               "children": [
                {
                 "id": "paw1",
                 "role": "foot",
                 "side": 1,
                 "index": 1,
                 "shape": {
                  "type": "hcapsule",
                  "w": 26,
                  "h": 15
                 },
                 "pos": {
                  "x": 0,
                  "y": 32.9
                 },
                 "rot": 0,
                 "sx": 1,
                 "sy": 1,
                 "z": 0,
                 "fill": "#7a4a24",
                 "children": [],
                 "limits": {
                  "min": -45,
                  "max": 45
                 }
                }
               ],
               "limits": {
                "min": -60,
                "max": 60
               },
               "flex": -1,
               "fold": true
              }
             ],
             "limits": {
              "min": -60,
              "max": 75
             },
             "fold": true
            },
            {
             "id": "leg2",
             "role": "leg",
             "side": -1,
             "index": 2,
             "shape": {
              "type": "capsule",
              "w": 21,
              "h": 35.42
             },
             "pos": {
              "x": -28,
              "y": 9.8
             },
             "rot": 0,
             "sx": 1,
             "sy": 1,
             "z": -2,
             "fill": "#a26a37",
             "children": [
              {
               "id": "low2",
               "role": "shin",
               "side": -1,
               "index": 2,
               "shape": {
                "type": "capsule",
                "w": 18,
                "h": 32.2
               },
               "pos": {
                "x": 0,
                "y": 32.2
               },
               "rot": 0,
               "sx": 1,
               "sy": 1,
               "z": 0,
               "fill": "#a26a37",
               "children": [
                {
                 "id": "paw2",
                 "role": "foot",
                 "side": -1,
                 "index": 2,
                 "shape": {
                  "type": "hcapsule",
                  "w": 26,
                  "h": 15
                 },
                 "pos": {
                  "x": 0,
                  "y": 32.268
                 },
                 "rot": 0,
                 "sx": 1,
                 "sy": 1,
                 "z": 0,
                 "fill": "#6b4120",
                 "children": [],
                 "limits": {
                  "min": -45,
                  "max": 45
                 }
                }
               ],
               "limits": {
                "min": -60,
                "max": 60
               },
               "flex": 1,
               "fold": true
              }
             ],
             "limits": {
              "min": -75,
              "max": 60
             },
             "fold": true
            },
            {
             "id": "leg3",
             "role": "leg",
             "side": 1,
             "index": 3,
             "shape": {
              "type": "capsule",
              "w": 21,
              "h": 35.42
             },
             "pos": {
              "x": 28,
              "y": 9.8
             },
             "rot": 0,
             "sx": 1,
             "sy": 1,
             "z": -2,
             "fill": "#a26a37",
             "children": [
              {
               "id": "low3",
               "role": "shin",
               "side": 1,
               "index": 3,
               "shape": {
                "type": "capsule",
                "w": 18,
                "h": 32.2
               },
               "pos": {
                "x": 0,
                "y": 32.2
               },
               "rot": 0,
               "sx": 1,
               "sy": 1,
               "z": 0,
               "fill": "#a26a37",
               "children": [
                {
                 "id": "paw3",
                 "role": "foot",
                 "side": 1,
                 "index": 3,
                 "shape": {
                  "type": "hcapsule",
                  "w": 26,
                  "h": 15
                 },
                 "pos": {
                  "x": 0,
                  "y": 32.268
                 },
                 "rot": 0,
                 "sx": 1,
                 "sy": 1,
                 "z": 0,
                 "fill": "#6b4120",
                 "children": [],
                 "limits": {
                  "min": -45,
                  "max": 45
                 }
                }
               ],
               "limits": {
                "min": -60,
                "max": 60
               },
               "flex": -1,
               "fold": true
              }
             ],
             "limits": {
              "min": -60,
              "max": 75
             },
             "fold": true
            },
            {
             "id": "head",
             "role": "head",
             "shape": {
              "type": "ellipse",
              "w": 76.96000000000001,
              "h": 66.56,
              "oy": -19.2
             },
             "pos": {
              "x": 0,
              "y": -29.4
             },
             "rot": 0,
             "sx": 1,
             "sy": 1,
             "z": -1,
             "fill": "#b8793f",
             "children": [
              {
               "id": "ear-1",
               "role": "ear",
               "side": -1,
               "index": 0,
               "shape": {
                "type": "teardrop",
                "w": 23.68,
                "h": 49.92
               },
               "pos": {
                "x": -32.56,
                "y": -39.68
               },
               "rot": 26,
               "sx": 1,
               "sy": 1,
               "z": 1,
               "fill": "#7a4a24",
               "children": [
                {
                 "id": "ear-1_1",
                 "role": "ear",
                 "side": -1,
                 "index": 1,
                 "pos": {
                  "x": 0,
                  "y": 24.96
                 },
                 "rot": 0,
                 "sx": 1,
                 "sy": 1,
                 "z": 0,
                 "children": [],
                 "limits": {
                  "min": -60,
                  "max": 60
                 },
                 "tip": {
                  "x": 0,
                  "y": 24.96
                 }
                }
               ],
               "limits": {
                "min": -90,
                "max": 90
               },
               "bend": true
              },
              {
               "id": "ear1",
               "role": "ear",
               "side": 1,
               "index": 0,
               "shape": {
                "type": "teardrop",
                "w": 23.68,
                "h": 49.92
               },
               "pos": {
                "x": 32.56,
                "y": -39.68
               },
               "rot": -26,
               "sx": 1,
               "sy": 1,
               "z": 1,
               "fill": "#7a4a24",
               "children": [
                {
                 "id": "ear1_1",
                 "role": "ear",
                 "side": 1,
                 "index": 1,
                 "pos": {
                  "x": 0,
                  "y": 24.96
                 },
                 "rot": 0,
                 "sx": 1,
                 "sy": 1,
                 "z": 0,
                 "children": [],
                 "limits": {
                  "min": -60,
                  "max": 60
                 },
                 "tip": {
                  "x": 0,
                  "y": 24.96
                 }
                }
               ],
               "limits": {
                "min": -90,
                "max": 90
               },
               "bend": true
              }
             ],
             "limits": {
              "min": -40,
              "max": 40
             }
            }
           ],
           "limits": {
            "min": -30,
            "max": 30
           }
          }
         ]
        },
        "footprint": 64
       }
      ],
      "spots": {
       "side": {
        "hip": {
         "node": "torso",
         "at": [
          -51,
          -3.5
         ],
         "hands": false
        },
        "chest": {
         "node": "torso",
         "at": [
          82.45,
          7
         ],
         "alt": [
          105.4,
          10.5
         ]
        },
        "head": {
         "node": "head",
         "at": [
          11.1,
          7.36
         ],
         "alt": [
          23.68,
          16
         ]
        },
        "mouth": {
         "node": "head",
         "at": [
          44.4,
          6.4
         ],
         "alt": [
          24.42,
          19.2
         ]
        }
       },
       "front": {
        "hip": {
         "node": "torso",
         "at": [
          35,
          7
         ],
         "mirror": true,
         "hands": false
        },
        "chest": {
         "node": "torso",
         "at": [
          0,
          3.5
         ],
         "hands": false
        },
        "head": {
         "node": "head",
         "at": [
          22.2,
          -48
         ],
         "mirror": true,
         "hands": false
        },
        "mouth": {
         "node": "head",
         "at": [
          0,
          1.28
         ],
         "hands": false
        }
       },
       "back": {
        "hip": {
         "node": "torso",
         "at": [
          35,
          7
         ],
         "mirror": true,
         "hands": false
        },
        "chest": {
         "node": "torso",
         "at": [
          0,
          3.5
         ],
         "hands": false
        },
        "head": {
         "node": "head",
         "at": [
          22.2,
          -48
         ],
         "mirror": true,
         "hands": false
        },
        "mouth": {
         "node": "head",
         "at": [
          0,
          1.28
         ],
         "hands": false
        }
       }
      }
     }
    },
    "says": "character.content: must be a character pack's content, with its node tree in content.tree"
   }
  },
  "clip_bad": {
   "says": "A wave's clip is neither \"pos\" nor \"neg\".",
   "fix": "Use \"pos\" (only the upper half) or \"neg\" (only the lower half), or leave it out.",
   "url": "https://jabbertoon.com/docs/errors/#clip_bad",
   "level": "error"
  },
  "content_hash_wrong": {
   "says": "The pack's content_hash is not the hash of its content.",
   "fix": "Set content_hash to the value the fix gives: sha256 of the canonical JSON of the content.",
   "url": "https://jabbertoon.com/docs/errors/#content_hash_wrong",
   "level": "error",
   "example": {
    "program": {
     "pack": 1,
     "id": "c4c:beh:wave_hello",
     "type": "behaviour",
     "version": "1.0.0",
     "name": "Wave hello",
     "description": "Raises the right arm and waves, with a happy little bob. Written with friendly blocks.",
     "author": {
      "id": "you",
      "name": "You"
     },
     "license": "cc0",
     "remixable": true,
     "derived_from": [],
     "preview": {
      "moves": [
       "wave_hello"
      ],
      "seconds": 6
     },
     "content_hash": "sha256:0000000000000000000000000000000000000000000000000000000000000000",
     "content": {
      "v": 1,
      "kind": "behaviour",
      "name": "wave_hello",
      "scripts": [
       {
        "body": [
         {
          "op": "mood",
          "mood": "happy"
         },
         {
          "op": "bob",
          "amp": 4,
          "every": 1.2
         },
         {
          "op": "setPart",
          "part": "right forearm",
          "deg": 20
         },
         {
          "op": "setPart",
          "part": "right arm",
          "deg": 150,
          "over": 0.35,
          "ease": "out"
         },
         {
          "op": "forever",
          "body": [
           {
            "op": "turnPart",
            "part": "right forearm",
            "deg": -40,
            "over": 0.2
           },
           {
            "op": "turnPart",
            "part": "right forearm",
            "deg": 40,
            "over": 0.2
           }
          ]
         }
        ]
       }
      ]
     }
    },
    "says": "content_hash: is not the hash of this content"
   }
  },
  "cut_needs_place_or_mood": {
   "says": "A cut changes neither the place nor the mood.",
   "fix": "Give a place, a mood (the grade), or both: {\"op\": \"cut\", \"place\": \"park\", \"mood\": \"bloom\"}.",
   "url": "https://jabbertoon.com/docs/errors/#cut_needs_place_or_mood",
   "level": "error"
  },
  "damping_negative": {
   "says": "A spring's damping is below 0.",
   "fix": "Give damping of 0 or more (0 swings on and on, 1 settles without swinging past).",
   "url": "https://jabbertoon.com/docs/errors/#damping_negative",
   "level": "error"
  },
  "does_also_not_boolean": {
   "says": "A does's \"also\" is not true or false.",
   "fix": "Give \"also\": true to add the move to what the character does, or leave it out.",
   "url": "https://jabbertoon.com/docs/errors/#does_also_not_boolean",
   "level": "error"
  },
  "does_needs_move": {
   "says": "A does does not say which move.",
   "fix": "Give \"behaviour\": a move's id like \"c4c:beh:wave_hello\", or a move written out.",
   "url": "https://jabbertoon.com/docs/errors/#does_needs_move",
   "suggest_from": "moves",
   "level": "error"
  },
  "does_setting_unknown": {
   "says": "A does gives a setting its own move does not have; the move ignores it.",
   "fix": "Use a setting of the move, or add it to the move's settings.",
   "url": "https://jabbertoon.com/docs/errors/#does_setting_unknown",
   "suggest_from": "names",
   "level": "warning"
  },
  "does_settings_not_object": {
   "says": "A does's settings (params) are not {name: value}.",
   "fix": "Write them as {\"t_in\": 2}.",
   "url": "https://jabbertoon.com/docs/errors/#does_settings_not_object",
   "level": "error"
  },
  "drive_needs_channel_and_value": {
   "says": "A drive block lacks \"ch\" or \"value\".",
   "fix": "Give both: \"ch\": \"dy\", \"value\": \"=sin(t) * 10\".",
   "url": "https://jabbertoon.com/docs/errors/#drive_needs_channel_and_value",
   "level": "error"
  },
  "dur_unknown_here": {
   "says": "A scene reads \"dur\", the scene's length, which is known only when the next scene is pinned with \"at\"; here it is Infinity.",
   "fix": "Pin the next scene with \"at\" (seconds from the start), or use a number of seconds.",
   "url": "https://jabbertoon.com/docs/errors/#dur_unknown_here",
   "level": "warning"
  },
  "ease_unknown": {
   "says": "A block names an ease the language does not have.",
   "fix": "Use linear, smooth, inout, in, out or snappy.",
   "url": "https://jabbertoon.com/docs/errors/#ease_unknown",
   "level": "error"
  },
  "empty_stage": {
   "says": "Nobody is on the stage for two seconds or more (a character with half of it, or its face, in the picture is on it).",
   "fix": "Bring a character on (enter, or place with x) sooner, or shorten the wait, or end the scene there.",
   "url": "https://jabbertoon.com/docs/errors/#empty_stage",
   "level": "warning"
  },
  "expression_invalid": {
   "says": "A formula does not read: a sign, a bracket or a word is out of place.",
   "fix": "Check the formula: numbers, names, + - * / ^ % and brackets, functions like sin(t); in JSON it starts with =.",
   "url": "https://jabbertoon.com/docs/errors/#expression_invalid",
   "level": "error"
  },
  "expression_unknown_function": {
   "says": "A formula uses a function the language does not have.",
   "fix": "Use one of its functions (sin, cos, abs, min, max, clamp, floor, round, sqrt and the others the spec lists).",
   "url": "https://jabbertoon.com/docs/errors/#expression_unknown_function",
   "level": "error"
  },
  "facing_bad": {
   "says": "A facing given as a number is neither 1 nor -1.",
   "fix": "Use 1 for facing right or -1 for facing left.",
   "url": "https://jabbertoon.com/docs/errors/#facing_bad",
   "level": "error"
  },
  "fails_when_played": {
   "says": "The program fails when it is played: a formula, a block or a character it names cannot run.",
   "fix": "Fix what the message names: a name in a formula that is not a setting, a variable or one the engine has; a character (who) that is not in the cast (give the cartoon a cast line with every character); or a loop that never waits (put a wait in it).",
   "url": "https://jabbertoon.com/docs/errors/#fails_when_played",
   "level": "error"
  },
  "falloff_large": {
   "says": "A falloff over 2 makes each segment swing more than twice the one before.",
   "fix": "Use a falloff of 2 or less.",
   "url": "https://jabbertoon.com/docs/errors/#falloff_large",
   "level": "warning"
  },
  "falloff_not_positive": {
   "says": "A falloff of 0 or less stops or flips every segment after the first.",
   "fix": "Give a falloff more than 0 (1 keeps every segment the same).",
   "url": "https://jabbertoon.com/docs/errors/#falloff_not_positive",
   "level": "warning"
  },
  "feet_off_stage": {
   "says": "A character's feet (y) are outside the picture, so it stands out of frame.",
   "fix": "Keep y between 0 (the top edge) and 1 (the bottom edge); the ground is 0.92.",
   "url": "https://jabbertoon.com/docs/errors/#feet_off_stage",
   "level": "warning"
  },
  "ffmpeg_failed": {
   "says": "ffmpeg stopped with an error, so the video was not made.",
   "fix": "Read the last lines of ffmpeg's own message (in the result), and try again; a full disk or a folder you cannot write to are the usual causes.",
   "url": "https://jabbertoon.com/docs/errors/#ffmpeg_failed",
   "level": "error"
  },
  "ffmpeg_missing": {
   "says": "Making a video needs ffmpeg, and none was found. Frames and contact sheets work without it.",
   "fix": "Get ffmpeg one of three ways: install it from https://ffmpeg.org/download.html or your package manager (winget install ffmpeg, brew install ffmpeg, apt install ffmpeg) so it is on your PATH; point at one you have with --ffmpeg <path> or JABBERTOON_FFMPEG=<path>; or run npm install ffmpeg-static where you run jabbertoon. Jabbertoon does not ship ffmpeg.",
   "url": "https://jabbertoon.com/docs/errors/#ffmpeg_missing",
   "level": "error"
  },
  "ffmpeg_no_h264": {
   "says": "The ffmpeg found cannot write H.264 video (it has none of libx264, h264_mf, h264_videotoolbox or libopenh264).",
   "fix": "Use a full build of ffmpeg (https://ffmpeg.org/download.html), or point at another with --ffmpeg <path>.",
   "url": "https://jabbertoon.com/docs/errors/#ffmpeg_no_h264",
   "level": "error"
  },
  "ffmpeg_no_webp": {
   "says": "The ffmpeg found cannot write animated WebP (it has no libwebp_anim encoder).",
   "fix": "Use a build of ffmpeg with libwebp (the full builds at https://ffmpeg.org/download.html have it).",
   "url": "https://jabbertoon.com/docs/errors/#ffmpeg_no_webp",
   "level": "error"
  },
  "field_ignored": {
   "says": "A block has a field it does not take; it is ignored.",
   "fix": "Remove the field, or check its spelling.",
   "url": "https://jabbertoon.com/docs/errors/#field_ignored",
   "suggest_from": "fields",
   "patchable": true,
   "level": "warning"
  },
  "file_exists": {
   "says": "A file with that name is already there, and it was not replaced.",
   "fix": "Give another name, or pass overwrite: true to replace it.",
   "url": "https://jabbertoon.com/docs/errors/#file_exists",
   "level": "error"
  },
  "file_not_found": {
   "says": "There is no file of that name in the output folder.",
   "fix": "Give the name of a .json or .txt file in the output folder (jabbertoon doctor says where the folder is).",
   "url": "https://jabbertoon.com/docs/errors/#file_not_found",
   "level": "error"
  },
  "file_unreadable": {
   "says": "That file could not be read: it is not a cartoon's JSON or screenplay text, or not UTF-8.",
   "fix": "Save the cartoon as UTF-8 JSON (.json) or screenplay text (.txt), then give its name again.",
   "url": "https://jabbertoon.com/docs/errors/#file_unreadable",
   "level": "error"
  },
  "folder_not_writable": {
   "says": "The output folder cannot be made or written to.",
   "fix": "Choose another folder with --out <folder> or JABBERTOON_OUT, one you can write to.",
   "url": "https://jabbertoon.com/docs/errors/#folder_not_writable",
   "level": "error"
  },
  "follow_after_bad": {
   "says": "A let-follow block follows something other than the body or a part.",
   "fix": "Follow \"body\" or a part, like \"head\".",
   "url": "https://jabbertoon.com/docs/errors/#follow_after_bad",
   "level": "error"
  },
  "follow_after_segment": {
   "says": "A let-follow block follows one segment or one leg, not a whole part.",
   "fix": "Follow the whole part (\"tail\", \"head\").",
   "url": "https://jabbertoon.com/docs/errors/#follow_after_segment",
   "level": "error"
  },
  "follow_channels_empty": {
   "says": "A follow block's list of channels is empty.",
   "fix": "Give at least one channel in \"ch\".",
   "url": "https://jabbertoon.com/docs/errors/#follow_channels_empty",
   "level": "error"
  },
  "follow_mood": {
   "says": "A follow block follows or moves \"mood\", which is not a number.",
   "fix": "Follow a number channel (dy, rot, a part).",
   "url": "https://jabbertoon.com/docs/errors/#follow_mood",
   "level": "error"
  },
  "follow_needs_channel_and_source": {
   "says": "A follow block lacks \"ch\" (what moves) or \"source\" (what it follows).",
   "fix": "Give both: \"ch\": \"part:tail\", \"source\": \"dy\".",
   "url": "https://jabbertoon.com/docs/errors/#follow_needs_channel_and_source",
   "level": "error"
  },
  "follow_source_bad": {
   "says": "A follow block's source is not one channel.",
   "fix": "Give the source as one channel, like \"dy\".",
   "url": "https://jabbertoon.com/docs/errors/#follow_source_bad",
   "level": "error"
  },
  "format_1_project": {
   "says": "That project file is the studio's older format (format 1), which this renderer does not read.",
   "fix": "Open it in the studio at https://jabbertoon.com/studio/ and save it again, or give the cartoon program itself.",
   "url": "https://jabbertoon.com/docs/errors/#format_1_project",
   "level": "error",
   "example": {
    "program": {
     "jabbertoon": "cartoon",
     "format": 1,
     "name": "Old",
     "cast": [
      null,
      null
     ],
     "names": [
      "A",
      "B"
     ],
     "scenes": []
    },
    "says": "That project file is the studio's older format (format 1), which this renderer does not read."
   }
  },
  "gait_bob_bad": {
   "says": "A walk cycle's bob is neither [base, amp] nor null.",
   "fix": "Give bob as [-2, 3] (two numbers), or null for no bob.",
   "url": "https://jabbertoon.com/docs/errors/#gait_bob_bad",
   "level": "error"
  },
  "glide_cut": {
   "says": "An enter, an exit or a glide (place … in N s) is cut off before it lands, when its scene ends; an exit cut off leaves the character on the stage.",
   "fix": "Give the enter, exit or place time to land: a wait after it, or pin the next scene later.",
   "level": "warning",
   "url": "https://jabbertoon.com/docs/errors/#glide_cut"
  },
  "hat_never_fires": {
   "says": "A move starts a script with a hat that never fires in a cartoon (touch, beat, loud, every), so those blocks never run.",
   "fix": "Use a hat that fires in a cartoon: when it starts, when the scene starts, when I start talking, when I stop talking.",
   "url": "https://jabbertoon.com/docs/errors/#hat_never_fires",
   "level": "warning"
  },
  "hat_unknown": {
   "says": "A move's script starts with a hat the language does not have.",
   "fix": "Start the script with a hat it has: start, talk-start, talk-end, scene, key, click (and beat, loud, every, touch, which never fire).",
   "url": "https://jabbertoon.com/docs/errors/#hat_unknown",
   "level": "error"
  },
  "hold_negative": {
   "says": "A reach holds for less than 0 s, so it lets go at once.",
   "fix": "Give hold 0 or more seconds.",
   "url": "https://jabbertoon.com/docs/errors/#hold_negative",
   "level": "warning"
  },
  "image_unreadable": {
   "says": "A picture in the project could not be read as an image.",
   "fix": "Give the picture as a PNG data URL (\"data:image/png;base64,...\"), as the studio saves it.",
   "url": "https://jabbertoon.com/docs/errors/#image_unreadable",
   "level": "error",
   "example": {
    "program": {
     "format": "jabbertoon-project",
     "version": 2,
     "cartoon": {
      "v": 1,
      "kind": "cartoon",
      "cast": {
       "A": {
        "name": "Ann"
       }
      },
      "scripts": [
       {
        "hat": {
         "on": "scene",
         "name": "One"
        },
        "body": [
         {
          "op": "say",
          "who": "A",
          "text": "Hi!"
         }
        ]
       }
      ]
     },
     "assets": {
      "characters": {
       "A": {
        "kind": "drawn",
        "png": "data:image/png;base64,aGVsbG8="
       }
      },
      "sounds": {}
     }
    },
    "says": "assets.characters.A.png: Character A's picture could not be read (that is not an image this renderer can read (Unsupported image type))."
   }
  },
  "input_hat_in_video": {
   "says": "A move starts a script with key or click, which fire only in the block editor, never in a video.",
   "fix": "In a video nobody presses a key or clicks: start it with \"when it starts\" or \"when the scene starts\" instead.",
   "url": "https://jabbertoon.com/docs/errors/#input_hat_in_video",
   "level": "warning"
  },
  "invalid_program": {
   "says": "The program does not validate, so it cannot be played.",
   "fix": "Validate the program and fix the errors it lists (each names its block by its path), then play it again.",
   "url": "https://jabbertoon.com/docs/errors/#invalid_program",
   "level": "error"
  },
  "job_unknown": {
   "says": "There is no render with that job here: a job lives only while the tool that started it runs.",
   "fix": "Start the render again with render_video.",
   "url": "https://jabbertoon.com/docs/errors/#job_unknown",
   "level": "error"
  },
  "lag_negative": {
   "says": "A lag below 0 runs the wave from the tip toward the body.",
   "fix": "Give a lag of 0 or more (0.08 s is the usual).",
   "url": "https://jabbertoon.com/docs/errors/#lag_negative",
   "level": "warning"
  },
  "lag_slow": {
   "says": "A lag of more than 1 s for each segment is very slow.",
   "fix": "Use a lag under 1 s (0.08 s is the usual).",
   "url": "https://jabbertoon.com/docs/errors/#lag_slow",
   "level": "warning"
  },
  "line_cut": {
   "says": "A line is cut off before it ends, when its scene ends.",
   "fix": "Give the line time to end: a wait after it, or pin the next scene later; a \"stop all\" ends lines too.",
   "url": "https://jabbertoon.com/docs/errors/#line_cut",
   "level": "warning"
  },
  "link_bad_name": {
   "says": "This holds a name a link cannot carry (__proto__, constructor or prototype), so no link was made.",
   "fix": "Rename that setting, variable or key.",
   "url": "https://jabbertoon.com/docs/errors/#link_bad_name",
   "level": "error",
   "example": {
    "program": {
     "v": 1,
     "kind": "behaviour",
     "name": "wave_hello",
     "scripts": [
      {
       "body": [
        {
         "op": "mood",
         "mood": "happy"
        },
        {
         "op": "bob",
         "amp": 4,
         "every": 1.2
        },
        {
         "op": "setPart",
         "part": "right forearm",
         "deg": 20
        },
        {
         "op": "setPart",
         "part": "right arm",
         "deg": 150,
         "over": 0.35,
         "ease": "out"
        },
        {
         "op": "forever",
         "body": [
          {
           "op": "turnPart",
           "part": "right forearm",
           "deg": -40,
           "over": 0.2
          },
          {
           "op": "turnPart",
           "part": "right forearm",
           "deg": 40,
           "over": 0.2
          }
         ]
        }
       ]
      }
     ],
     "params": {
      "constructor": 1
     }
    },
    "says": "program: That uses a name a link cannot carry (__proto__, constructor or prototype), so no link was made. Rename it, then make the link again."
   }
  },
  "link_too_big": {
   "says": "This holds more than a link can carry (over 1 MB), so no link was made.",
   "fix": "Make it smaller: fewer scenes, shorter moves, or save it to a file instead.",
   "url": "https://jabbertoon.com/docs/errors/#link_too_big",
   "level": "error"
  },
  "look_colors_not_object": {
   "says": "A look's colors is not an object; the renderer uses its default colours.",
   "fix": "Write colors as {\"body\": \"#ffcf77\", \"skin\": \"#9e8a78\", \"acc\": \"#6a4c93\"}.",
   "url": "https://jabbertoon.com/docs/errors/#look_colors_not_object",
   "level": "warning"
  },
  "look_colour_bad": {
   "says": "A colour is not written as one; the renderer uses its default.",
   "fix": "Write a colour as # and 3 or 6 hex digits, like \"#ffcf77\".",
   "url": "https://jabbertoon.com/docs/errors/#look_colour_bad",
   "level": "warning"
  },
  "look_colour_outside_colors": {
   "says": "A colour is written straight in the look, where the renderer does not read it.",
   "fix": "Move it into \"colors\": {\"colors\": {\"body\": \"#ffcf77\", \"skin\": \"#9e8a78\", \"acc\": \"#6a4c93\"}}.",
   "url": "https://jabbertoon.com/docs/errors/#look_colour_outside_colors",
   "patchable": true,
   "level": "warning"
  },
  "look_colour_unknown": {
   "says": "A colour slot is not one a character has; it is ignored.",
   "fix": "Use the slots body, skin and acc (list_characters says what each one paints).",
   "url": "https://jabbertoon.com/docs/errors/#look_colour_unknown",
   "level": "warning"
  },
  "look_facing_bad": {
   "says": "A look's facing is neither 1 nor -1; the renderer takes the art as drawn.",
   "fix": "Set the look's facing to 1 (the art faces right, or the front) or -1 (it faces left).",
   "url": "https://jabbertoon.com/docs/errors/#look_facing_bad",
   "level": "warning"
  },
  "look_field_unknown": {
   "says": "A look has a field the renderer does not use; it is ignored.",
   "fix": "Use template, style, shape, look, proportions, colors, stretch, options and facing only.",
   "url": "https://jabbertoon.com/docs/errors/#look_field_unknown",
   "suggest_from": "fields",
   "level": "warning"
  },
  "look_given_twice": {
   "says": "A look gives both the studio's name and the engine's name for one thing (look and style, or proportions and shape); the engine's wins.",
   "fix": "Keep one of the two: style (or look), shape (or proportions).",
   "url": "https://jabbertoon.com/docs/errors/#look_given_twice",
   "patchable": true,
   "level": "warning"
  },
  "look_name_not_text": {
   "says": "A name in a look (template, style, shape and so on) is not text; the renderer uses its own.",
   "fix": "Give it as text: \"template\": \"dog\".",
   "url": "https://jabbertoon.com/docs/errors/#look_name_not_text",
   "level": "warning"
  },
  "look_not_object": {
   "says": "A cast member's look is not an object.",
   "fix": "Write the look as {\"template\": \"dog\", \"style\": \"outlined\", \"colors\": {\"body\": \"#ffcf77\"}}.",
   "url": "https://jabbertoon.com/docs/errors/#look_not_object",
   "level": "error"
  },
  "look_options_not_object": {
   "says": "A look's options is not an object; it is ignored.",
   "fix": "Write options as {\"name\": value}, the options list_characters gives for the template.",
   "url": "https://jabbertoon.com/docs/errors/#look_options_not_object",
   "level": "warning"
  },
  "look_outside_picture": {
   "says": "A cast member's look names a picture from outside (an emoji, an image address, an avatar), which jabbertoon.com never fetches, so render_video refuses that character.",
   "fix": "Draw it as one of the six ready-made characters instead ({\"template\": \"dog\"}), and leave the picture out.",
   "url": "https://jabbertoon.com/docs/errors/#look_outside_picture",
   "level": "error",
   "example": {
    "program": {
     "v": 1,
     "kind": "cartoon",
     "cast": {
      "A": {
       "name": "Ann",
       "look": {
        "template": "kid",
        "image": "https://example.com/ann.png"
       }
      }
     },
     "scripts": [
      {
       "hat": {
        "on": "scene",
        "name": "One"
       },
       "body": [
        {
         "op": "say",
         "who": "A",
         "text": "Hi!"
        }
       ]
      }
     ]
    },
    "says": "cast.A.look.image: \"image\" names a picture from outside, which jabbertoon.com never fetches, so render_video refuses this character"
   }
  },
  "look_stretch_bad": {
   "says": "A stretch is not a number more than 0; it is ignored.",
   "fix": "Give each stretch as a number more than 0 (1 is as drawn).",
   "url": "https://jabbertoon.com/docs/errors/#look_stretch_bad",
   "level": "warning"
  },
  "look_stretch_field_unknown": {
   "says": "A look's stretch has a part other than head, body and legs; it is ignored.",
   "fix": "Stretch only head, body and legs.",
   "url": "https://jabbertoon.com/docs/errors/#look_stretch_field_unknown",
   "level": "warning"
  },
  "look_stretch_not_object": {
   "says": "A look's stretch is not {head, body, legs}; it is ignored.",
   "fix": "Write stretch as {\"head\": 1.2, \"body\": 1, \"legs\": 0.9} (1 is as drawn).",
   "url": "https://jabbertoon.com/docs/errors/#look_stretch_not_object",
   "level": "warning"
  },
  "mood_missing": {
   "says": "A mood block does not say which mood.",
   "fix": "Give \"mood\": happy, sad, angry, surprised or normal.",
   "url": "https://jabbertoon.com/docs/errors/#mood_missing",
   "level": "error"
  },
  "move_block_in_scene": {
   "says": "A scene uses a block that moves a character, which is a move's job.",
   "fix": "Put the block in a move (a behaviour program) and start it with does {who, behaviour}.",
   "url": "https://jabbertoon.com/docs/errors/#move_block_in_scene",
   "level": "error"
  },
  "move_cut": {
   "says": "A move given a time (does … for N s) is cut off before it is done, when its scene ends.",
   "fix": "A does with a for does not wait: put a wait after it, or give the scene time for the move to end.",
   "level": "warning",
   "url": "https://jabbertoon.com/docs/errors/#move_cut"
  },
  "move_id_bad": {
   "says": "A does names a move that is not a pack id.",
   "fix": "Give a move's id, like \"c4c:beh:walk\" (list_moves gives them all).",
   "url": "https://jabbertoon.com/docs/errors/#move_id_bad",
   "suggest_from": "moves",
   "level": "error"
  },
  "move_version_not_text": {
   "says": "A does gives a move's version that is not text.",
   "fix": "Give the version as text, like \"1.0.0\", or leave it out.",
   "url": "https://jabbertoon.com/docs/errors/#move_version_not_text",
   "level": "error"
  },
  "move_wrong_body": {
   "says": "A character does a move that does not suit its body: it moves nothing on it, or it moves legs the character does not have.",
   "fix": "Give this character a move made for its body (list_moves says what each move works on), or another character.",
   "url": "https://jabbertoon.com/docs/errors/#move_wrong_body",
   "level": "warning"
  },
  "name_of_a_character": {
   "says": "A scene reads \"loud\" or \"talking\", which belong to a character; a scene reads 0.",
   "fix": "Read them in a move (a behaviour) that the scene starts with does.",
   "url": "https://jabbertoon.com/docs/errors/#name_of_a_character",
   "level": "warning"
  },
  "name_unknown": {
   "says": "A formula uses a name that is not a setting, a variable or one the engine gives, so the move fails when it plays.",
   "fix": "Use a name the program has (its settings and variables) or one the engine gives: t, tau, local, dur, loud, talking, random, pi, e.",
   "url": "https://jabbertoon.com/docs/errors/#name_unknown",
   "suggest_from": "names",
   "level": "warning"
  },
  "node_missing": {
   "says": "Making a video from Python is done by the jabbertoon command, which needs Node.js 22 or later, and neither the jabbertoon command nor npx was found.",
   "fix": "Install Node.js 22 or later (https://nodejs.org/), which brings npx, then render again; or give render() the jabbertoon command you have, with cli= or JABBERTOON_CLI.",
   "url": "https://jabbertoon.com/docs/errors/#node_missing",
   "level": "error"
  },
  "node_too_old": {
   "says": "This Node.js is older than the jabbertoon tool needs (22 or later).",
   "fix": "Install Node.js 22 or later from https://nodejs.org/.",
   "url": "https://jabbertoon.com/docs/errors/#node_too_old",
   "level": "error"
  },
  "not_a_cartoon": {
   "says": "That is not something Jabbertoon can draw: it is not a cartoon, scene or move program, a cartoon pack, or a project file.",
   "fix": "Give a cartoon program ({\"v\": 1, \"kind\": \"cartoon\", \"cast\": {...}, \"scripts\": [...]}), a cartoon pack, a .jabbertoon.json project (version 2), or a move program.",
   "url": "https://jabbertoon.com/docs/errors/#not_a_cartoon",
   "level": "error"
  },
  "not_found": {
   "says": "There is nothing of that name.",
   "fix": "Use a name the tool lists (list_moves for a move).",
   "url": "https://jabbertoon.com/docs/errors/#not_found",
   "level": "error"
  },
  "not_json": {
   "says": "That is not something a link can carry, so no link was made.",
   "fix": "Give plain JSON values only: objects, lists, text, numbers, true, false and null.",
   "url": "https://jabbertoon.com/docs/errors/#not_json",
   "level": "error"
  },
  "not_supported_here": {
   "says": "This door does not do that: it is done by the tool on your own computer (reading a file, playing the cartoon through).",
   "fix": "Send the cartoon itself, or use the jabbertoon tool on your own computer.",
   "url": "https://jabbertoon.com/docs/errors/#not_supported_here",
   "level": "error"
  },
  "number_not_finite": {
   "says": "A number is not finite (it is too big, or not a number at all).",
   "fix": "Give an ordinary number.",
   "url": "https://jabbertoon.com/docs/errors/#number_not_finite",
   "level": "error"
  },
  "offline": {
   "says": "The tool runs with --offline, so the report was not sent.",
   "fix": "Run the tool without --offline to send reports, or write to hello@jabbertoon.com.",
   "url": "https://jabbertoon.com/docs/errors/#offline",
   "level": "error"
  },
  "offstage": {
   "says": "A character is shown partly out of the frame (more than 2% of its width or its height past an edge, or a quarter of its face out of the picture) while not entering or leaving.",
   "fix": "Place the character where all of it is in the picture, its face too: no more than 2% of its width or its height past an edge (the issue gives the places that keep it in when there are some: a dog or a cat, drawn wider than it is tall, needs more room from an edge than a person), its feet, y, near the ground at 0.92; or let it exit if it should leave. When its own move takes it out, the issue names the move.",
   "url": "https://jabbertoon.com/docs/errors/#offstage",
   "level": "warning"
  },
  "op_unknown": {
   "says": "A block's \"op\" is not one the language has.",
   "fix": "Use a block the language has (the spec lists them; a scene uses say, does, caption, cut, enter, exit, place, mood and the control blocks).",
   "url": "https://jabbertoon.com/docs/errors/#op_unknown",
   "level": "error"
  },
  "option_unknown": {
   "says": "A cast member's look gives an option its character does not have, so it does nothing.",
   "fix": "Use the character's own options (list_characters gives each one's), or leave the option out.",
   "url": "https://jabbertoon.com/docs/errors/#option_unknown",
   "level": "warning",
   "example": {
    "program": {
     "v": 1,
     "kind": "cartoon",
     "cast": {
      "A": {
       "name": "Blob",
       "look": {
        "template": "monster",
        "options": {
         "wings": 2
        }
       }
      }
     },
     "scripts": [
      {
       "hat": {
        "on": "scene",
        "name": "One"
       },
       "body": [
        {
         "op": "say",
         "who": "A",
         "text": "Hi!"
        }
       ]
      }
     ]
    },
    "says": "cast.A.look.options: the monster has no option \"wings\", so it does nothing"
   }
  },
  "option_value_unknown": {
   "says": "A look option has a value the character does not take, so the site reads it as one of the values it does take.",
   "fix": "Use one of the values list_characters gives for that option.",
   "url": "https://jabbertoon.com/docs/errors/#option_value_unknown",
   "level": "warning",
   "example": {
    "program": {
     "v": 1,
     "kind": "cartoon",
     "cast": {
      "A": {
       "name": "Blob",
       "look": {
        "template": "monster",
        "options": {
         "eyes": 7
        }
       }
      }
     },
     "scripts": [
      {
       "hat": {
        "on": "scene",
        "name": "One"
       },
       "body": [
        {
         "op": "say",
         "who": "A",
         "text": "Hi!"
        }
       ]
      }
     ]
    },
    "says": "cast.A.look.options.eyes: the monster's option \"eyes\" (Eyes) takes 2 (Two) or 1 (One), not 7, so the site reads it as \"Two\""
   }
  },
  "overlap": {
   "says": "Two characters stand over each other for half a second or more: one covers half or more of the other, one face covers half or more of the other face, or the one drawn in front (the later in the cast, in the order a link gives it) covers half or more of the face of the one behind.",
   "fix": "Move one of them away from the other: the issue gives the place, and the smaller size when only a smaller one has room, that keeps them apart with all of each in the picture; or have one exit first. When a move carries one onto the other, the issue names it.",
   "url": "https://jabbertoon.com/docs/errors/#overlap",
   "level": "warning"
  },
  "own_move_not_a_move": {
   "says": "A does was given a program of its own that is not a move.",
   "fix": "Give the move \"kind\": \"behaviour\".",
   "url": "https://jabbertoon.com/docs/errors/#own_move_not_a_move",
   "level": "error"
  },
  "pack_invalid": {
   "says": "A field of the pack's manifest is not right (its id, version, type, name, licence or another).",
   "fix": "Fix the field named, as the pack format describes: https://jabbertoon.com/docs/packs/.",
   "url": "https://jabbertoon.com/docs/errors/#pack_invalid",
   "level": "error",
   "example": {
    "program": {
     "pack": 1,
     "id": "c4c:beh:wave_hello",
     "type": "behaviour",
     "version": "one",
     "name": "Wave hello",
     "description": "Raises the right arm and waves, with a happy little bob. Written with friendly blocks.",
     "author": {
      "id": "you",
      "name": "You"
     },
     "license": "cc0",
     "remixable": true,
     "derived_from": [],
     "preview": {
      "moves": [
       "wave_hello"
      ],
      "seconds": 6
     },
     "content_hash": "sha256:a7cc2f929a2014dc87c812a99f9156a9b5c4e09db56940506eff667f99f27463",
     "content": {
      "v": 1,
      "kind": "behaviour",
      "name": "wave_hello",
      "scripts": [
       {
        "body": [
         {
          "op": "mood",
          "mood": "happy"
         },
         {
          "op": "bob",
          "amp": 4,
          "every": 1.2
         },
         {
          "op": "setPart",
          "part": "right forearm",
          "deg": 20
         },
         {
          "op": "setPart",
          "part": "right arm",
          "deg": 150,
          "over": 0.35,
          "ease": "out"
         },
         {
          "op": "forever",
          "body": [
           {
            "op": "turnPart",
            "part": "right forearm",
            "deg": -40,
            "over": 0.2
           },
           {
            "op": "turnPart",
            "part": "right forearm",
            "deg": 40,
            "over": 0.2
           }
          ]
         }
        ]
       }
      ]
     }
    },
    "says": "version: semver x.y.z"
   }
  },
  "part_not_a_name": {
   "says": "A block's \"part\" is not text.",
   "fix": "Name the part as text: \"right arm\", \"tail\", \"ears\".",
   "url": "https://jabbertoon.com/docs/errors/#part_not_a_name",
   "level": "error"
  },
  "part_not_drawn": {
   "says": "A block moves the neck, which no character draws, so it shows nothing.",
   "fix": "Move the head or the torso instead.",
   "url": "https://jabbertoon.com/docs/errors/#part_not_drawn",
   "level": "warning"
  },
  "part_role_unknown": {
   "says": "A part channel names a part no character has, so nothing moves.",
   "fix": "Use a part of the vocabulary: head, torso, hips, arm, forearm, hand, leg, shin, foot, tail, ear, wing, fin, claw, snout, nose, hair, hat, eye, brow.",
   "url": "https://jabbertoon.com/docs/errors/#part_role_unknown",
   "level": "warning"
  },
  "part_unknown": {
   "says": "A block names a part the language does not know.",
   "fix": "Name a part like \"right arm\", \"left leg\", \"tail\", \"ears\", \"head\" or \"body\".",
   "url": "https://jabbertoon.com/docs/errors/#part_unknown",
   "level": "error"
  },
  "path_outside_folder": {
   "says": "That file name would put the file outside the output folder.",
   "fix": "Give a plain file name (letters, digits, spaces, dots, dashes), with no folder in it.",
   "url": "https://jabbertoon.com/docs/errors/#path_outside_folder",
   "level": "error"
  },
  "pinned_scene_squeezed": {
   "says": "A scene runs 0 s: the next scene's pinned start had passed when it began.",
   "fix": "Pin the next scene later, or shorten what comes before this scene.",
   "url": "https://jabbertoon.com/docs/errors/#pinned_scene_squeezed",
   "level": "warning"
  },
  "place_entry_bad": {
   "says": "A place is neither a background's name nor {background, grade}.",
   "fix": "Write the place as \"meadow\" or {\"background\": \"meadow\", \"grade\": \"bloom\"}.",
   "url": "https://jabbertoon.com/docs/errors/#place_entry_bad",
   "level": "error"
  },
  "place_needs_a_value": {
   "says": "A place block gives none of x, y, h and facing.",
   "fix": "Give at least one: {\"op\": \"place\", \"who\": \"A\", \"x\": 0.3}.",
   "url": "https://jabbertoon.com/docs/errors/#place_needs_a_value",
   "level": "error"
  },
  "place_not_a_name": {
   "says": "A place is not given as a name.",
   "fix": "Give the place as text: a name of the places (or a background, like \"meadow\").",
   "url": "https://jabbertoon.com/docs/errors/#place_not_a_name",
   "level": "error"
  },
  "place_unknown": {
   "says": "A cut or a scene names a place the places do not have.",
   "fix": "Use a name of the places, or add it to \"places\".",
   "url": "https://jabbertoon.com/docs/errors/#place_unknown",
   "suggest_from": "places",
   "level": "error"
  },
  "places_not_object": {
   "says": "The places are not an object of places by name.",
   "fix": "Write places as {\"park\": {\"background\": \"meadow\", \"grade\": \"normal\"}}.",
   "url": "https://jabbertoon.com/docs/errors/#places_not_object",
   "level": "error"
  },
  "play_warning": {
   "says": "The player warned about something while it played the cartoon; the issue gives its words.",
   "fix": "Read what the player says and change the block it names.",
   "level": "warning",
   "url": "https://jabbertoon.com/docs/errors/#play_warning"
  },
  "point_field_unknown": {
   "says": "A point has a field other than x and y.",
   "fix": "Keep only x and y in the point.",
   "url": "https://jabbertoon.com/docs/errors/#point_field_unknown",
   "suggest_from": "fields",
   "level": "error"
  },
  "point_needs_x_and_y": {
   "says": "A point is missing x or y.",
   "fix": "Give both x and y.",
   "url": "https://jabbertoon.com/docs/errors/#point_needs_x_and_y",
   "level": "error"
  },
  "point_not_object": {
   "says": "A reach \"to\" is not a point {x, y}.",
   "fix": "Give the point as {\"x\": 80, \"y\": 300} (pixels from the feet, x toward the front).",
   "url": "https://jabbertoon.com/docs/errors/#point_not_object",
   "level": "error"
  },
  "program_kind_unknown": {
   "says": "The program's \"kind\" is not one the language has.",
   "fix": "Set \"kind\" to \"cartoon\" (scenes with a cast), \"scene\" (one scene) or \"behaviour\" (a move for one character).",
   "url": "https://jabbertoon.com/docs/errors/#program_kind_unknown",
   "level": "error"
  },
  "program_kind_wrong": {
   "says": "The program's kind is not the one this file or pack holds: a cartoon holds a kind \"cartoon\" program, a scene pack a kind \"scene\" one.",
   "fix": "Set the program's kind to the one named.",
   "url": "https://jabbertoon.com/docs/errors/#program_kind_wrong",
   "level": "error",
   "example": {
    "program": {
     "pack": 1,
     "id": "c4c:beh:wave_hello",
     "type": "behaviour",
     "version": "1.0.0",
     "name": "Wave hello",
     "description": "Raises the right arm and waves, with a happy little bob. Written with friendly blocks.",
     "author": {
      "id": "you",
      "name": "You"
     },
     "license": "cc0",
     "remixable": true,
     "derived_from": [],
     "preview": {
      "moves": [
       "wave_hello"
      ],
      "seconds": 6
     },
     "content_hash": "sha256:a7cc2f929a2014dc87c812a99f9156a9b5c4e09db56940506eff667f99f27463",
     "content": {
      "v": 1,
      "kind": "cartoon",
      "name": "wave_hello",
      "scripts": [
       {
        "body": [
         {
          "op": "mood",
          "mood": "happy"
         },
         {
          "op": "bob",
          "amp": 4,
          "every": 1.2
         },
         {
          "op": "setPart",
          "part": "right forearm",
          "deg": 20
         },
         {
          "op": "setPart",
          "part": "right arm",
          "deg": 150,
          "over": 0.35,
          "ease": "out"
         },
         {
          "op": "forever",
          "body": [
           {
            "op": "turnPart",
            "part": "right forearm",
            "deg": -40,
            "over": 0.2
           },
           {
            "op": "turnPart",
            "part": "right forearm",
            "deg": 40,
            "over": 0.2
           }
          ]
         }
        ]
       }
      ]
     }
    },
    "says": "content.kind: must be \"behaviour\""
   }
  },
  "program_not_object": {
   "says": "What was given is not a program: a program is a JSON object.",
   "fix": "Give the program as an object: {\"v\": 1, \"kind\": \"cartoon\", \"cast\": {...}, \"scripts\": [...]}.",
   "url": "https://jabbertoon.com/docs/errors/#program_not_object",
   "level": "error"
  },
  "program_scripts_not_list": {
   "says": "The program's \"scripts\" is not a list.",
   "fix": "Make \"scripts\" a list of scripts: [{\"hat\": {...}, \"body\": [...]}].",
   "url": "https://jabbertoon.com/docs/errors/#program_scripts_not_list",
   "level": "error"
  },
  "program_version": {
   "says": "The program's \"v\" is not 1, the only version of the language.",
   "fix": "Set \"v\" to 1.",
   "url": "https://jabbertoon.com/docs/errors/#program_version",
   "patchable": true,
   "level": "error"
  },
  "reach_needs_target": {
   "says": "A reach gives neither a point (to) nor a spot (at).",
   "fix": "Give \"to\" a point {x, y} or \"at\" a spot: hip, head, chest or mouth.",
   "url": "https://jabbertoon.com/docs/errors/#reach_needs_target",
   "level": "error"
  },
  "reach_not_a_limb": {
   "says": "A reach or a let-go moves something that is not a hand or a foot.",
   "fix": "Reach with a hand or a foot: \"right hand\", \"left foot\", \"hands\", \"feet\".",
   "url": "https://jabbertoon.com/docs/errors/#reach_not_a_limb",
   "level": "error"
  },
  "reach_offset_without_spot": {
   "says": "A reach moves a point with dx or dy, which only move a spot.",
   "fix": "Use dx and dy with \"at\" (a spot); a point is a place of its own.",
   "url": "https://jabbertoon.com/docs/errors/#reach_offset_without_spot",
   "level": "error"
  },
  "reach_to_and_at": {
   "says": "A reach gives both a point (to) and a spot (at).",
   "fix": "Give one: \"to\" a point {x, y}, or \"at\" a spot (hip, head, chest, mouth).",
   "url": "https://jabbertoon.com/docs/errors/#reach_to_and_at",
   "level": "error"
  },
  "render_failed": {
   "says": "Drawing a frame failed.",
   "fix": "Read the message: it names what could not be drawn. If it names the canvas library or a texture, install the package again (npm install) so that library is complete; otherwise send the code and the message (never the cartoon) with report_problem.",
   "url": "https://jabbertoon.com/docs/errors/#render_failed",
   "level": "error"
  },
  "report_not_sent": {
   "says": "The report could not be sent to jabbertoon.com.",
   "fix": "Try again later, or write to hello@jabbertoon.com.",
   "url": "https://jabbertoon.com/docs/errors/#report_not_sent",
   "level": "error"
  },
  "runtime_cap": {
   "says": "The render took longer than its time limit, so it was cut short: the result is partial.",
   "fix": "Render a shorter part, a smaller size, or give it a longer time limit.",
   "url": "https://jabbertoon.com/docs/errors/#runtime_cap",
   "level": "warning"
  },
  "say_needs_text": {
   "says": "A say block has no words.",
   "fix": "Give the line as text: \"text\": \"Hello!\".",
   "url": "https://jabbertoon.com/docs/errors/#say_needs_text",
   "level": "error"
  },
  "scene_block_in_move": {
   "says": "A move uses a scene block (say, does, caption, cut, enter, exit, place).",
   "fix": "Use scene blocks in a program of kind \"cartoon\" or \"scene\"; a move moves one character.",
   "url": "https://jabbertoon.com/docs/errors/#scene_block_in_move",
   "level": "error"
  },
  "scene_hat_conflict": {
   "says": "Two scripts of one scene give it different places, moods or pinned starts.",
   "fix": "Give the place, mood and \"at\" once, or the same in each script of the scene.",
   "url": "https://jabbertoon.com/docs/errors/#scene_hat_conflict",
   "level": "error"
  },
  "scene_hat_field_ignored": {
   "says": "A scene hat has a field it does not take; it is ignored.",
   "fix": "Keep only on, name, place, mood and at on a scene hat.",
   "url": "https://jabbertoon.com/docs/errors/#scene_hat_field_ignored",
   "suggest_from": "fields",
   "patchable": true,
   "level": "warning"
  },
  "scene_hat_invalid": {
   "says": "The scene hats cannot be grouped into scenes as written.",
   "fix": "Give every script of a cartoon a scene hat {\"on\": \"scene\", \"name\": \"…\"}, and give a scene's place, mood and \"at\" once.",
   "url": "https://jabbertoon.com/docs/errors/#scene_hat_invalid",
   "level": "error"
  },
  "scene_pinned_before_earlier": {
   "says": "A scene is pinned before an earlier scene's pinned start, so the scene before it is cut off at once and it starts late.",
   "fix": "Pin the scenes in order: each \"at\" later than the one before.",
   "url": "https://jabbertoon.com/docs/errors/#scene_pinned_before_earlier",
   "level": "warning"
  },
  "scene_program_one_scene": {
   "says": "A scene program names more than one scene.",
   "fix": "Make it a cartoon (kind \"cartoon\") to have several scenes, or give every script the same scene name.",
   "url": "https://jabbertoon.com/docs/errors/#scene_program_one_scene",
   "level": "error"
  },
  "scene_script_hat": {
   "says": "A script of a scene program starts with a hat other than the scene's.",
   "fix": "Start each script with the scene (no hat, or {\"on\": \"scene\"}); key and click are the block editor's.",
   "url": "https://jabbertoon.com/docs/errors/#scene_script_hat",
   "level": "error"
  },
  "scene_start_bad": {
   "says": "A scene's pinned start (\"at\") is not a time of 0 s or more.",
   "fix": "Give \"at\" as seconds from the cartoon's start (a number, 0 or more).",
   "url": "https://jabbertoon.com/docs/errors/#scene_start_bad",
   "level": "error"
  },
  "scene_unknown": {
   "says": "The cartoon has no scene of that name.",
   "fix": "Use one of the scene names the cartoon has (validate's summary lists them).",
   "url": "https://jabbertoon.com/docs/errors/#scene_unknown",
   "suggest_from": "names",
   "level": "error"
  },
  "segments_bad": {
   "says": "Segments is not a whole number from 1 to 16.",
   "fix": "Give segments as a whole number from 1 to 16.",
   "url": "https://jabbertoon.com/docs/errors/#segments_bad",
   "level": "error"
  },
  "segments_not_a_chain": {
   "says": "A block gives \"segments\" for a part that is not a chain; it moves whole, so segments does nothing.",
   "fix": "Leave segments out, or use a chain part (tail, body, ears, hair).",
   "url": "https://jabbertoon.com/docs/errors/#segments_not_a_chain",
   "level": "warning"
  },
  "server_error": {
   "says": "The tool failed on its own side.",
   "fix": "Try again; if it keeps failing, call report_problem.",
   "url": "https://jabbertoon.com/docs/errors/#server_error",
   "level": "error"
  },
  "shape_unknown": {
   "says": "A wave names a shape the language does not have.",
   "fix": "Use sin, cos, abssin, possin, dampsin, square, saw or tri.",
   "url": "https://jabbertoon.com/docs/errors/#shape_unknown",
   "level": "error"
  },
  "side_unknown": {
   "says": "An entrance or an exit names a side the stage does not have.",
   "fix": "Use left, right, top or bottom.",
   "url": "https://jabbertoon.com/docs/errors/#side_unknown",
   "level": "error"
  },
  "size_not_positive": {
   "says": "A character's size (h) is not more than 0.",
   "fix": "Give h as a share of the stage's height more than 0: 0.5 is half the height.",
   "url": "https://jabbertoon.com/docs/errors/#size_not_positive",
   "level": "error"
  },
  "sound_not_placed": {
   "says": "A recording in the project is not for any line of the cartoon, so it would not be heard.",
   "fix": "Key each recording in assets.sounds by the line it belongs to: \"line:<n>\" (or \"<n>\"), n counting the lines (say blocks) from 0 in the order the cartoon speaks them; or pass allow_substitutes: true to make it without that recording (listed in the result).",
   "url": "https://jabbertoon.com/docs/errors/#sound_not_placed",
   "level": "error",
   "example": {
    "program": {
     "format": "jabbertoon-project",
     "version": 2,
     "cartoon": {
      "v": 1,
      "kind": "cartoon",
      "cast": {
       "A": {
        "name": "Ann",
        "look": {
         "template": "kid"
        }
       }
      },
      "scripts": [
       {
        "hat": {
         "on": "scene",
         "name": "One"
        },
        "body": [
         {
          "op": "say",
          "who": "A",
          "text": "Hi!"
         }
        ]
       }
      ]
     },
     "assets": {
      "characters": {},
      "sounds": {
       "line:5": {
        "mime": "audio/wav",
        "data": "UklGRg=="
       }
      }
     }
    },
    "says": "assets.sounds.line:5: The recording \"line:5\" is not for any line: the cartoon has 1 line (0 to 0), so there is no line 5. It would not be heard, so nothing was made."
   }
  },
  "sound_unreadable": {
   "says": "A sound in the project could not be read.",
   "fix": "Give the sound as base64 audio (WAV, MP3, OGG or WebM) with its mime type, as the studio saves a recording; ffmpeg reads it.",
   "url": "https://jabbertoon.com/docs/errors/#sound_unreadable",
   "level": "error",
   "example": {
    "program": {
     "format": "jabbertoon-project",
     "version": 2,
     "cartoon": {
      "v": 1,
      "kind": "cartoon",
      "cast": {
       "A": {
        "name": "Ann",
        "look": {
         "template": "kid"
        }
       }
      },
      "scripts": [
       {
        "hat": {
         "on": "scene",
         "name": "One"
        },
        "body": [
         {
          "op": "say",
          "who": "A",
          "text": "Hi!"
         }
        ]
       }
      ]
     },
     "assets": {
      "characters": {},
      "sounds": {
       "line:0": {
        "mime": "audio/wav",
        "data": ""
       }
      }
     }
    },
    "says": "assets.sounds.line:0: The recording \"line:0\" (line 0) has no sound in it: a recording is {\"mime\": ..., \"data\": \"<base64>\"}."
   }
  },
  "speed_given_twice": {
   "says": "A block gives more than one of w, hz and every.",
   "fix": "Give one speed: w (radians a second), hz (times a second) or every (seconds each time).",
   "url": "https://jabbertoon.com/docs/errors/#speed_given_twice",
   "level": "error"
  },
  "speed_not_positive": {
   "says": "A line's speed is not more than 0.",
   "fix": "Give speed more than 0 (1 is the usual; 0.85 a little slower).",
   "url": "https://jabbertoon.com/docs/errors/#speed_not_positive",
   "level": "error"
  },
  "spot_unknown": {
   "says": "A reach names a spot the body does not have.",
   "fix": "Use one of the spots: hip, head, chest, mouth.",
   "url": "https://jabbertoon.com/docs/errors/#spot_unknown",
   "level": "error"
  },
  "spring_fast": {
   "says": "A spring faster than 6 a second swings further and settles differently than a real spring would.",
   "fix": "Use hz of 6 or less for a close follow-through.",
   "url": "https://jabbertoon.com/docs/errors/#spring_fast",
   "level": "warning"
  },
  "spring_not_positive": {
   "says": "A spring's speed (hz) is not more than 0.",
   "fix": "Give hz more than 0: how many times a second the spring swings back (2 is the usual).",
   "url": "https://jabbertoon.com/docs/errors/#spring_not_positive",
   "level": "error"
  },
  "spring_too_fast": {
   "says": "A spring swings back more than 60 times a second.",
   "fix": "Give hz of 60 or less (up to 6 follows closely).",
   "url": "https://jabbertoon.com/docs/errors/#spring_too_fast",
   "level": "error"
  },
  "sync_bad": {
   "says": "A wave's clock is neither \"local\" nor \"start\".",
   "fix": "Use \"local\" (from when the block starts) or \"start\" (the move's own clock).",
   "url": "https://jabbertoon.com/docs/errors/#sync_bad",
   "level": "error"
  },
  "talks_offstage": {
   "says": "A character says a line while it is out of the picture (less than half of it in, and its face out) for most of the line.",
   "fix": "Let the character enter (or place it) before its line, or give the line to someone on stage.",
   "url": "https://jabbertoon.com/docs/errors/#talks_offstage",
   "level": "warning"
  },
  "text_bad_indent": {
   "says": "That line is indented to a level no line above it has.",
   "fix": "Indent each block two spaces more than the line it belongs to, and keep the lines of one body at the same indent.",
   "url": "https://jabbertoon.com/docs/errors/#text_bad_indent",
   "level": "error"
  },
  "text_bad_json": {
   "says": "The JSON after the block's name does not read as that block.",
   "fix": "Check the JSON: names and text in double quotes, no comma after the last item, and \"op\" the same as the word before it; or write the block in words.",
   "url": "https://jabbertoon.com/docs/errors/#text_bad_json",
   "level": "error"
  },
  "text_bad_value": {
   "says": "A value there cannot be read.",
   "fix": "Write a number (0.5), a formula in brackets ((t * 2)), or text in double quotes (\"Hello\").",
   "url": "https://jabbertoon.com/docs/errors/#text_bad_value",
   "level": "error"
  },
  "text_block_outside_script": {
   "says": "A block line is not under a hat.",
   "fix": "Put a hat line above it (when it starts in a move, scene \"Name\" in a cartoon) and indent the block two spaces under it.",
   "url": "https://jabbertoon.com/docs/errors/#text_block_outside_script",
   "level": "error"
  },
  "text_branch_alone": {
   "says": "A branch line (— 1:) is not under at the same time:.",
   "fix": "Put each — 1:, — 2: … line (or - 1:, - 2: …) under an at the same time: line, indented two spaces.",
   "url": "https://jabbertoon.com/docs/errors/#text_branch_alone",
   "level": "error"
  },
  "text_cast_field_unknown": {
   "says": "That cast detail is not one the text knows.",
   "fix": "Use pack, template, style, look, shape, proportions, legs (4 legs), at x … y … size … facing …, voice, colors body …, stretch, art faces, options or note, separated by \" · \" (or \"|\").",
   "url": "https://jabbertoon.com/docs/errors/#text_cast_field_unknown",
   "level": "error"
  },
  "text_cast_unknown_id": {
   "says": "A cast detail line names an id the cast: line does not have.",
   "fix": "Add the id to the cast: line (cast: A = Sunny, B = Grump), or fix the id at the start of the detail line.",
   "url": "https://jabbertoon.com/docs/errors/#text_cast_unknown_id",
   "level": "error"
  },
  "text_child_not_allowed": {
   "says": "That line is indented under a line that holds no lines.",
   "fix": "Unindent it, or move it under a hat or a block that holds a body (for, until, repeat, forever, while, if, between, at the same time).",
   "url": "https://jabbertoon.com/docs/errors/#text_child_not_allowed",
   "level": "error"
  },
  "text_else_alone": {
   "says": "Else: is not right after a block at its indent.",
   "fix": "Put else: at the same indent as its if …: line, right after the lines of the if.",
   "url": "https://jabbertoon.com/docs/errors/#text_else_alone",
   "level": "error"
  },
  "text_expected": {
   "says": "The line reads well up to here, then has something else than the text expects.",
   "fix": "Write the words the block takes at that place (the error says which), the way the Screenplay text section of the spec shows the block.",
   "url": "https://jabbertoon.com/docs/errors/#text_expected",
   "level": "error"
  },
  "text_form_remote_unsupported": {
   "says": "The remote door reads a program as JSON only, not as screenplay text.",
   "fix": "Send the program as JSON (the studio's paste box and the local tool read the text and give its JSON), or use the local tool, which reads the text itself.",
   "url": "https://jabbertoon.com/docs/errors/#text_form_remote_unsupported",
   "level": "error"
  },
  "text_heading_late": {
   "says": "A heading comes after a scene or a hat.",
   "fix": "Move the heading (cast:, places:, settings:, variables:) above the first scene or hat.",
   "url": "https://jabbertoon.com/docs/errors/#text_heading_late",
   "level": "error"
  },
  "text_heading_not_first": {
   "says": "The cartoon line (or the scene program line) is not the first line of the text.",
   "fix": "Make cartoon \"Name\" the first line: take out what is above it (a sentence, or a ``` line), or move the line to the top.",
   "url": "https://jabbertoon.com/docs/errors/#text_heading_not_first",
   "level": "error",
   "example": {
    "text": "cast: A = Ann\ncartoon \"Beach day\"\nscene \"One\"\n  A says \"Hi!\"",
    "says": "Line 2, column 1: the cartoon line (or the scene program line) is not the first line of the text."
   }
  },
  "text_heading_twice": {
   "says": "That heading is given twice.",
   "fix": "Give each heading (cartoon, cast:, places:, settings:, variables:) once, at the top.",
   "url": "https://jabbertoon.com/docs/errors/#text_heading_twice",
   "level": "error"
  },
  "text_not_text": {
   "says": "That is not text.",
   "fix": "Give the screenplay text as a string.",
   "url": "https://jabbertoon.com/docs/errors/#text_not_text",
   "level": "error"
  },
  "text_program_not_alone": {
   "says": "A program written as its JSON (program {…}) is the whole text, and a line is outside it.",
   "fix": "Write the program either as one program {…} line of JSON or in the screenplay words, not both.",
   "url": "https://jabbertoon.com/docs/errors/#text_program_not_alone",
   "level": "error"
  },
  "text_unclosed_bracket": {
   "says": "A bracket is not closed.",
   "fix": "Close the bracket with ) on the same line: a formula, (t * 2), or the list at the end of a line, (happy, voice af_sky).",
   "url": "https://jabbertoon.com/docs/errors/#text_unclosed_bracket",
   "level": "error"
  },
  "text_unclosed_quote": {
   "says": "A quote is not closed.",
   "fix": "End the text with a double quote (\") on the same line; write a quote inside text as \\\".",
   "url": "https://jabbertoon.com/docs/errors/#text_unclosed_quote",
   "level": "error"
  },
  "text_unknown_line": {
   "says": "That line is not a block, a hat or a heading the screenplay text knows.",
   "fix": "Write the line the way the Screenplay text section of the spec shows it: in a scene, for example A says \"Hello!\" (happy), A does wave_hello or place A at x 0.3 in 1 s; in a move, turn 30° in 0.5 s.",
   "url": "https://jabbertoon.com/docs/errors/#text_unknown_line",
   "level": "error"
  },
  "texture_unavailable": {
   "says": "A look's texture (Storybook's paper grain, Crayon's wax) cannot be drawn here, so the frame was not drawn without it.",
   "fix": "Install the package again (npm install) so its canvas library is complete, or use a look without a texture (flat, outlined, soft, bold).",
   "url": "https://jabbertoon.com/docs/errors/#texture_unavailable",
   "level": "error"
  },
  "timeout": {
   "says": "The request took longer than the online tools allow and was stopped.",
   "fix": "Try again in a few seconds; if it happens again, send a smaller program, or check it with the tool on your own computer.",
   "url": "https://jabbertoon.com/docs/errors/#timeout",
   "level": "error"
  },
  "too_large": {
   "says": "The request (more than 256 KB) or its answer (more than 4 MB) is too large.",
   "fix": "Send one program, pack or cartoon at a time, without data it does not need.",
   "url": "https://jabbertoon.com/docs/errors/#too_large",
   "level": "error"
  },
  "turn_view_instant": {
   "says": "A turn of 0 s or less changes the view at once, without the squash.",
   "fix": "Give the turn a time (\"over\": 0.24 is the usual), or use a view block for a change at once.",
   "url": "https://jabbertoon.com/docs/errors/#turn_view_instant",
   "level": "warning"
  },
  "unknown_background": {
   "says": "A scene or a cut is at a place whose background the studio does not have.",
   "fix": "Use one of the studio's backgrounds: beach, meadow, classroom, stage, space or city; or give the place one on the places line (places: kitchen = classroom).",
   "url": "https://jabbertoon.com/docs/errors/#unknown_background",
   "suggest_from": "places",
   "level": "error"
  },
  "unknown_grade": {
   "says": "A scene, a place or a cut gives a grade (the picture's colouring) the studio does not have.",
   "fix": "Use one of the scene grades: normal, angry, bloom, soft or sad.",
   "url": "https://jabbertoon.com/docs/errors/#unknown_grade",
   "level": "warning"
  },
  "unknown_mood": {
   "says": "A line, a \"looks\" block or a move gives a mood that no face shows.",
   "fix": "Use one of the moods a face shows: happy, sad, angry, surprised or normal.",
   "url": "https://jabbertoon.com/docs/errors/#unknown_mood",
   "level": "warning"
  },
  "unknown_move": {
   "says": "A character does a move the studio does not have; in the studio it idles instead.",
   "fix": "Use a move the studio has (list_moves gives every one, with what it works on), such as walk, wave_hello or bounce.",
   "url": "https://jabbertoon.com/docs/errors/#unknown_move",
   "suggest_from": "moves",
   "level": "warning"
  },
  "unknown_pack": {
   "says": "A cast member names a character pack Jabbertoon does not ship: the studio has no such character, and render_video refuses it.",
   "fix": "Use one of the shipped character packs (c4c:char:person, c4c:char:kid, c4c:char:dog, c4c:char:cat, c4c:char:bird, c4c:char:monster), or draw a ready-made character with a look ({\"look\": {\"template\": \"dog\"}}).",
   "url": "https://jabbertoon.com/docs/errors/#unknown_pack",
   "patchable": true,
   "level": "error",
   "example": {
    "program": {
     "v": 1,
     "kind": "cartoon",
     "cast": {
      "A": {
       "name": "Puff",
       "pack": "c4c:char:dragon"
      }
     },
     "scripts": [
      {
       "hat": {
        "on": "scene",
        "name": "One"
       },
       "body": [
        {
         "op": "say",
         "who": "A",
         "text": "Hi!"
        }
       ]
      }
     ]
    },
    "says": "cast.A.pack: \"c4c:char:dragon\" is not one of the character packs shipped with Jabbertoon (c4c:char:person, c4c:char:kid, c4c:char:dog, c4c:char:cat, c4c:char:bird, c4c:char:monster): the studio has no such character, and render_video refuses it"
   }
  },
  "unknown_shape": {
   "says": "A cast member's look names a body shape (look.shape) the site does not have, so it is drawn with the classic shape.",
   "fix": "Use one of the three body shapes: classic, bighead or tall (list_looks gives them).",
   "url": "https://jabbertoon.com/docs/errors/#unknown_shape",
   "patchable": true,
   "level": "warning",
   "example": {
    "program": {
     "v": 1,
     "kind": "cartoon",
     "cast": {
      "A": {
       "name": "Rex",
       "look": {
        "template": "dog",
        "shape": "round"
       }
      }
     },
     "scripts": [
      {
       "hat": {
        "on": "scene",
        "name": "One"
       },
       "body": [
        {
         "op": "say",
         "who": "A",
         "text": "Hi!"
        }
       ]
      }
     ]
    },
    "says": "cast.A.look.shape: \"round\" is not one of the three body shapes, so the site draws it with the classic shape"
   }
  },
  "unknown_style": {
   "says": "A cast member's look names a style (look.style) the site does not have, so it is drawn in the page's own look.",
   "fix": "Use one of the six looks: flat, outlined, soft, storybook, bold or crayon (list_looks gives them).",
   "url": "https://jabbertoon.com/docs/errors/#unknown_style",
   "suggest_from": "looks",
   "patchable": true,
   "level": "warning",
   "example": {
    "program": {
     "v": 1,
     "kind": "cartoon",
     "cast": {
      "A": {
       "name": "Rex",
       "look": {
        "template": "dog",
        "style": "neon"
       }
      }
     },
     "scripts": [
      {
       "hat": {
        "on": "scene",
        "name": "One"
       },
       "body": [
        {
         "op": "say",
         "who": "A",
         "text": "Hi!"
        }
       ]
      }
     ]
    },
    "says": "cast.A.look.style: \"neon\" is not one of the six looks, so the site draws it in the page's own look"
   }
  },
  "unknown_template": {
   "says": "A cast member's template (its kind of body) is not one the studio has.",
   "fix": "Use one of the studio's templates: person, kid, dog, cat, bird or monster (list_characters gives them).",
   "url": "https://jabbertoon.com/docs/errors/#unknown_template",
   "suggest_from": "templates",
   "level": "error"
  },
  "unknown_tool": {
   "says": "That tool is not one this door has.",
   "fix": "Ask tools/list for the tools this door has (the tool on your own computer has preview and render_video too), and call one of them by its name.",
   "level": "error",
   "url": "https://jabbertoon.com/docs/errors/#unknown_tool"
  },
  "unknown_voice": {
   "says": "A character speaks in a voice the studio does not have.",
   "fix": "Use one of the studio's voices (list_characters gives them), such as af_heart or am_puck.",
   "url": "https://jabbertoon.com/docs/errors/#unknown_voice",
   "suggest_from": "voices",
   "level": "warning"
  },
  "unreadable": {
   "says": "The checker could not read this at all: it is not the shape of anything Jabbertoon checks.",
   "fix": "Give it the shape its format describes: a program https://jabbertoon.com/docs/language/, a pack or a character https://jabbertoon.com/docs/packs/.",
   "url": "https://jabbertoon.com/docs/errors/#unreadable",
   "level": "error"
  },
  "value_not_number": {
   "says": "A value that must be a number is neither a number nor a formula.",
   "fix": "Give a number (0.5), or a formula as text starting with = (\"=t * 2\").",
   "url": "https://jabbertoon.com/docs/errors/#value_not_number",
   "level": "error"
  },
  "value_not_text": {
   "says": "A value that must be text is not.",
   "fix": "Give it as text in quotes.",
   "url": "https://jabbertoon.com/docs/errors/#value_not_text",
   "level": "error"
  },
  "variable_not_a_name": {
   "says": "A variable block's \"var\" is not a name.",
   "fix": "Give the variable's name as text: \"var\": \"score\".",
   "url": "https://jabbertoon.com/docs/errors/#variable_not_a_name",
   "level": "error"
  },
  "variable_start_not_number": {
   "says": "A variable starts at something other than a number.",
   "fix": "Start each variable at a number (\"vars\": {\"n\": 0}); set it to a formula with a set block as the script runs.",
   "url": "https://jabbertoon.com/docs/errors/#variable_start_not_number",
   "level": "error"
  },
  "view_needs_to": {
   "says": "A view block does not say which view.",
   "fix": "Give \"to\": front, side or back.",
   "url": "https://jabbertoon.com/docs/errors/#view_needs_to",
   "level": "error"
  },
  "view_unknown": {
   "says": "A view block names a view the characters do not have.",
   "fix": "Use front, side or back.",
   "url": "https://jabbertoon.com/docs/errors/#view_unknown",
   "level": "error"
  },
  "voices_failed": {
   "says": "The voices could not speak a line, so there is no speech.",
   "fix": "Run \"jabbertoon voices status\" to check the install, or install them again.",
   "url": "https://jabbertoon.com/docs/errors/#voices_failed",
   "level": "error"
  },
  "voices_not_installed": {
   "says": "The voices are not installed on this machine, so there is no speech. Nothing is downloaded during a render.",
   "fix": "Run \"jabbertoon voices install\" once (about 500 MB on disk: the voice engine and its 92 MB voice model, in a folder of your own), then render again; or render without voices.",
   "url": "https://jabbertoon.com/docs/errors/#voices_not_installed",
   "level": "error"
  },
  "wave_needs_channel": {
   "says": "A wave does not say what it moves.",
   "fix": "Give \"ch\", a channel like \"dy\" or \"part:arm:1\".",
   "url": "https://jabbertoon.com/docs/errors/#wave_needs_channel",
   "level": "error"
  },
  "who_missing": {
   "says": "A scene block does not say who.",
   "fix": "Give \"who\", an id of the cast: \"who\": \"A\".",
   "url": "https://jabbertoon.com/docs/errors/#who_missing",
   "level": "error"
  },
  "who_not_in_cast": {
   "says": "A scene block names someone who is not in the cast.",
   "fix": "Use an id of the cast, or add the character to the cast.",
   "url": "https://jabbertoon.com/docs/errors/#who_not_in_cast",
   "suggest_from": "names",
   "level": "error"
  },
  "window_end_unknown": {
   "says": "A between block counts back from the scene's end, which is known only when the next scene is pinned; here it is never reached.",
   "fix": "Pin the next scene with \"at\", or give from and to as seconds from the scene's start.",
   "url": "https://jabbertoon.com/docs/errors/#window_end_unknown",
   "level": "warning"
  }
 }
}
