Menu

Diagnostic codes

On this page

Generated from packages/core/src/diagnostics/codes.ts by pnpm run docs. Codes are stable: agents can branch on them. rule names a pedagogical guardrail (A1…I1) or a line of the LMS delivery checklist (LMS-n): see Rules. An error under a rule stops a build but not a preview (elabora preview, the app’s Aperçu): the course runs without what the rule asks, and the preview shows it as it is.

Errors (block the build)

Code Title Fix Rule
E_FILE_MISSING Required file missing Create the file (elabora init scaffolds a project).
E_JSON_PARSE Invalid JSON Fix the JSON syntax at the reported position.
E_SCHEMA Does not match the schema Read the schema named in the message (or call get_block_schema) and correct the value at path.
E_FORMAT_NEWER Course in a newer format than this Elabora reads Update Elabora (the app, or the elabora command) to work on this course; this version reads its own format and migrates older ones. Do not lower the format by hand: what the newer format added would be lost or misread.
E_DUPLICATE_ID Duplicate id Ids of sections, screens, blocks, layers and events share one namespace: each must be unique in the whole course (a section cannot have the id of a screen). Rename the new element, never a published one.
E_SCREEN_ID_MISMATCH Screen id differs from its file name Rename the file to screens/<id>.json or fix the id.
E_SCREEN_NOT_FOUND Screen listed in course.json has no file Create screens/<id>.json or remove the id from course.json sections.
E_SCREEN_LISTED_TWICE Screen listed more than once in course.json Each screen appears exactly once in sections.
E_UNKNOWN_REFERENCE Reference to an unknown element Use an existing id (see the message for the kind of element expected).
E_ASSET_MISSING Asset file not found Add the file under assets/ or fix the path.
E_SOURCE_REFERENCED A course file points into sources/ sources/ holds the files the author gave (briefs, decks, recordings), which are never published and keep their metadata. Import what the course shows into assets/ (elabora media import . sources/<file> for an image, audio or video) and point to that.
E_FILENAME_NOT_PORTABLE File name not accepted by every LMS Use ASCII letters, digits, “-”, “_” and “.” only (RFC 3986 unreserved). No spaces or accents. LMS-8
E_EXTERNAL_RESOURCE External resource in content Copy the file into assets/ and reference it locally: packages must work without network access. LMS-8
E_MEDIA_UNREADABLE Media file cannot be read The file is damaged, incomplete (still downloading or syncing) or not media: replace it, or import the original again with elabora media import.
E_MEDIA_RENDITION Media rendition could not be made Builds below the high media quality encode renditions of the masters with ffmpeg: install it (or set ELABORA_FFMPEG and ELABORA_FFPROBE), read the encoder message, or build at the high quality.
E_PLAN_NOT_APPROVED No validated version of the plan A release build needs a version of the plan the client validated. A person makes it (the app’s « Créer la V1 », elabora plan version), sends it (Exporter, elabora plan export) and records the client’s validation (« Valider… », elabora plan approve --by "<name>"); agents never do. Use –draft builds meanwhile. A5
E_PLAN_VERSION_INVALID A version of the plan that does not hold together A version never changes once made: its plan must give its contentHash, and its number must be its file name (plan-versions/V<n>.json). Bring the file back from the history (elabora history, elabora undo) or a backup; never edit a version by hand, and make a new one instead (elabora plan version). A5
E_PLAN_ITEM_UNCOVERED Plan item not covered by any screen Add a screen whose covers lists this item, or remove the item from the plan (elabora plan write, MCP elabora_write_plan). A1
E_PLAN_REFERENCE Unknown plan reference Reference an id that exists in plan.json (objectives, items, lockedTexts, questions, sources). A1
E_LOCKED_TEXT_NOT_USED Validated text of the plan not used Add a text, heading or callout block with textRef set to this id on a screen covering the item. A5
E_LOCKED_TEXT_OUTSIDE_ITEM Validated text used on a screen that does not cover its item Use it on a screen whose covers includes the plan item that owns the text. A1
E_PLAN_QUESTION_NOT_USED Validated question not used Add a quiz block (numeric block for numeric questions) with questionRef set to this id on a screen covering the item. A5
E_BLOCK_TEXT_SOURCE Text source ambiguous Set exactly one of markdown/text or textRef.
E_QUIZ_SOURCE Quiz source ambiguous Either set questionRef only, or set stem, mode and options (inline question).
E_PLAN_OBJECTIVE_UNUSED Objective not served by any plan item Reference it from a plan item, or remove it (elabora plan write). A1
E_FEEDBACK_MISSING Option without elaborated feedback Write, for every option, why it is right or wrong and what to remember (not just Correct/Incorrect). D1
E_QUIZ_SINGLE_MULTIPLE_CORRECT Single-choice question with several correct options Set mode to multiple or keep one correct option.
E_FILLIN_NO_BLANK Fill-in without blanks it can use Write each blank in the Markdown as [[answer]], other accepted answers after | ([[DNS|serveur DNS]]): one to three per sentence, 12 at most, each with an answer.
E_SORT_TARGET Sort whose items and targets do not fit Give the sort its items (4 to 8 is best). pairs: as many targets as items, each item naming a target of its own. categories: 2 to 4 targets, each item naming one of them. order: the items in the right order, without targets. Ids of items and of targets are unique in the block.
E_QUIZ_PICTURE Quiz on pictures without its pictures or zones presentation images: give each option its image and alt. presentation image: give the quiz its image and alt, and each option its x and y (0 to 1 from the top left of the picture). A plan question (questionRef) has no pictures: write the question inline, or fork the quiz to add them to the plan’s options.
E_GALLERY_COMPARE Before and after without exactly two images A gallery in the compare presentation shows two images, the first before and the second after: keep two, or choose grid or mosaic for more.
E_STEPS_FIGURE Scroll steps without what their figure follows presentation scroll: figure replace and build need step images (build: transparent layers the size of figureImage); figure focus needs figureImage and a region { x, y, w, h } (0 to 1 of the picture) on the steps it outlines.
E_BLOCK_ITEM_DUPLICATE Two items of a block with the same id Each item of a steps block or an interactive picture has its own id: visited marks, translations and conversions name items by id. Rename the new one, never one learners already saw. In a carousel, intro and summary are the ids of its first and last items.
E_SPEECH_SPEAKER A character block names a speaker the course does not have A speech block’s speaker is a speaker of course.json speakers (its name, colour and look are read there): add the character there, or use an existing id.
E_IMAGE_ALT_MISSING Image without text alternative Write alt as the information the image carries, or set decorative: true if it carries none. F3
E_VIDEO_CAPTIONS_MISSING Video with sound without captions Give the video its captions from a WebVTT or SubRip file (elabora media captions . <block> <file.vtt|.srt>, MCP elabora_set_captions): the file is written under assets/captions/, SubRip converted to WebVTT, and captions names it. A silent animation plays as a loop (loop: true, with alt); a video that carries no information is decorative: true. F3
E_MEDIA_TRANSCRIPT_MISSING Video or sound without transcript Write the transcript: what is said and shown. A video without sound may give alt instead; a sound or a video that carries no information is decorative: true. F3
E_VIDEO_ALT_MISSING Looping video without text alternative Write alt as what the animation shows, or set decorative: true if it carries none. F3
E_THEME_CONTRAST Insufficient colour contrast Adjust the theme tokens to reach WCAG 2.2 AA (4.5:1 text, 3:1 focus). F1
E_HEADING_ORDER Heading level skipped Headings go 2 → 3 → 4 without skipping a level. F1
E_OBJECT_A11Y_ALTERNATIVE Free object without text alternative Fill textAlternative with an equivalent activity or a full description. F3
E_PLAYER_SETTING_MOVED Player setting moved into course.json player Write it in course.json player as the message says (elabora player . –enable/–disable/–set, MCP elabora_player), and remove it from navigation or narration: the outline, the progress and the bottom bar’s position are player items and options since 19 October 2026 (D58).
E_PLAYER_ITEM_DUPLICATE Player item listed twice Each item (logo, title, progress, outline, controls, resources, glossary, credits, display, language, previous, next, exit) goes in one bar, once, and each bar has one spacer: remove the second entry (elabora player . –move <item>:<bar>[:<index>] moves it, MCP elabora_player move).
E_SOUND_MISSING A sound the course names is not in assets/sounds/ Add the sound (elabora sound add . <file or library id> –id <id>), or name one the course has (elabora sound list .).
E_SOUND_LICENSE A sound whose licence does not let it ship Replace the sound with one under CC0, a public-domain mark, CC BY or CC BY-SA (elabora sound search . “<words>”), or write its licence in its sidecar assets/sounds/<id>.json when you know it (license: CC0-1.0, CC-BY-4.0…, own for a sound the author made or bought with every right). Non-commercial (NC) and no-derivatives (ND) licences cannot ship: courses are sold, and sounds are cut and mixed.
E_SOUND_BACKGROUND A track of music or ambience over a range that does not work Give the track a range of screens of the course, from before to (elabora sound background), with one track at a time on each screen: two tracks on one screen would play over each other.
E_SOUND_PART A part of a sound that is not in its file Give start and end in seconds inside the sound, end after start (its length: elabora sound list .), or leave them out to play it whole.
E_DUPLICATE_ENTRY Two glossary entries or resources with the same id Give each glossary entry and each resource its own id: texts link to entries by id (glossary:<id>).
E_RESOURCE_URL Resource link that is not an https:// address Give the resource an https:// address (https://intranet.example.com/charte), or a file of assets/ instead (asset).
E_GLOSSARY_TERM_UNKNOWN Link to a glossary entry that does not exist Link to an entry of course.json glossary ([mot](glossary:<id>)), or add the entry with MCP elabora_player (glossary: the whole list, the new entry with them): the ids are in the message.
E_EVENT_TARGET Trigger target of the wrong kind click targets a button (or a component with buttons, tabs or disclosures; name is one of their names), quiz.submitted a quiz or numeric block (or a fork), decision.selected a decision, object.event a free-object block, layer.closed a layer of this screen.
E_VISITED_TARGET Visited condition on a block without that control visited names a block with controls (a button block, or a component with data-t-click buttons, tabs or disclosures); name, when given, is one of the names of its controls (see the message).
E_ACTION_TARGET Action target invalid Point go-to at an existing screen (or next/previous), layers and blocks at elements of this screen.
E_VARIABLE_TYPE Value does not match the variable type Use a value of the declared type (and an allowed option for choice variables).
E_VARIABLE_STRING_LENGTH String variable without maxLength Set maxLength so the suspend data budget can be computed. LMS-3
E_OBJECT_EVENT_UNDECLARED Free object event not declared in its manifest Use an event name listed in object.manifest.json events.
E_OBJECT_PROP_VALUE Free object prop value invalid Use a declared prop with a value matching its schema (type, bounds, enum).
E_NARRATION_LINE_DUPLICATE Two narration lines with the same id Give every line of a screen its own id (l1, l2…), every track counted: the screen’s narration, each layer’s and each dialogue’s lines (with or without a voice, replies included). Cues, translations and the audio files (assets/narration/<language>/<screen>/<line>.m4a) are named by it.
E_NARRATION_SPEAKER Narration speaker unknown Name a speaker of course.json speakers (each declared once), or declare it there with the name learners read in captions: { “id”: “leila”, “name”: “Leïla” }.
E_NARRATION_STEP_ORDER Narration lines out of step order Lines are spoken in the order they are written and each step is one stretch of the timeline: put the lines of a step after those of the steps before it.
E_TIMELINE_CUE Timeline cue or action without a timeline to follow timeline.reached names a line of the screen’s narration or of a layer’s (at.line), or seconds from the start of a step on a screen without narration (at.seconds; with layer, from the opening of a layer without narration); timeline.ended and the actions pause-timeline, play-timeline and seek-timeline need a timed screen: narrated (narration.lines), or whose blocks or events are timed in seconds; with layer, a layer of the screen with a timeline of its own (a narration, or timed blocks: D62).
E_TIMELINE_ANCHOR_MISSING Anchor on a word or line the narration does not say An anchor names a line of the screen’s narration and, with word, one or a few words that line says (case, punctuation and apostrophes aside; occurrence picks a word said more than once). The line’s text changed or the anchor is mistyped: anchor to words the line says (elabora timeline <screen> lists the lines and the anchors), or drop word to anchor to the line. Until then the block comes at the start of the line. In a translation, place the anchor’s marker on the words of that language.
E_TIMING_SECONDS_NARRATED Seconds on a narrated screen A narrated screen anchors its moments to its lines and words, so that they hold when the voice is generated again, recorded or translated: { “line”: “l2” }, { “line”: “l2”, “word”: “imprimante” }, with offset for a delay. Seconds are for screens without narration.
E_TIMELINE_ANCHOR_TRACK Anchor on a line of another timeline Each timeline plays on its own (D62): a block or a cue of a layer anchors to the lines of that layer’s narration (layers[].narration.lines), a block or a cue of the screen to the screen’s (narration.lines), never to a line the other one says. Anchor to a line of its own timeline, move the line into the narration it belongs to, or move the block; an event whose layer names another timeline than its line’s keeps one of the two. Until then it falls back to the start of its timeline.
E_TIMING_EFFECT_UNKNOWN Unknown effect Use an effect of the player (none, fade, rise, slide, zoom, wipe, draw), or one the theme declares in course.json theme.effects (its stylesheet defines @keyframes t-fx-<name>).
E_TIMING_ORDER Block that leaves before it comes Its timing.out falls at or before its timing.in (the message gives both times): learners never see it. Anchor out to a later word or line, or remove out (the block then stays until the end of the screen).
E_ACTIVITY_LEAVES_UNANSWERED Question or control that leaves before learners can use it An activity, or a block learners click, leaves (timing.out) while playback goes on, before it stops for the learner at the end of a step: learners may not have had the time to answer or to use it. Let it stay until the end of its step’s stretch (playback waits there in learner mode, or once answered with steps that open answered), until the end of the screen, or remove its timing.out.
E_NARRATION_TRACK Narration track could not be made The build lays the lines of a screen end to end with ffmpeg: install it (or set ELABORA_FFMPEG), check that each line’s audio plays (the message has ffmpeg’s words), or import it again.
E_MASTERY_SCORE_MISSING masteryScore required Set completion.masteryScore (percent) or use reportAs completed-incomplete. LMS-13
E_SUSPEND_DATA_BUDGET Worst-case suspend data exceeds the LMS limit Reduce persisted state: fewer persisted variables, shorter string maxLength, smaller free-object persistState.maxLength, or split the course. LMS-3
E_PACKAGE_TOO_LARGE Package larger than the LMS accepts Lower the media quality: elabora build --media-quality medium (or low), or set delivery.mediaQuality in course.json; the message (and details) give the size at each quality, the one that fits and the heaviest files. Otherwise shorten the heaviest media, host long videos on a video platform and link to them, or split the course. LMS-8
E_PACKAGE_TOO_MANY_FILES Too many files for the LMS Merge assets or split the course. LMS-8
E_COMPRESSION_RATIO Compression ratio above the LMS limit Store already-compressed or random-like data, or split very repetitive files. LMS-8
E_LMS_UNKNOWN LMS unknown to Elabora Use the id of an LMS profile (elabora profiles lists them) in delivery.lms, or leave it out. LMS-8
E_FORBIDDEN_EXTENSION File type refused by the LMS Remove server-side files from the package. LMS-8
E_STANDARD_NOT_SUPPORTED Target standard not supported by the LMS profile Build SCORM 1.2 for this LMS. LMS-9
E_WEB_URL Web address not usable Give the absolute address where the module’s index.html will be served, with https:// (or http://): elabora build --target web --url https://example.org/modules/gearset/.
E_WEB_IMAGE Sharing image not usable Give a PNG, JPEG or WebP file (1200×630 px reads well everywhere), a path in the course folder (assets/…) or an absolute path: --image assets/images/cover.jpg.
E_WEB_REVIEW_ORIGIN Review page origin not usable Give the origin of the review page that will show the module, https:// and its host, without a path: elabora build --target web --review-origin https://revue.elabora.studio (repeat it for a development page on http://localhost:&lt;port>).
E_MANIFEST_NOT_AT_ROOT imsmanifest.xml is not at the root of the ZIP Repackage with the manifest at the root. LMS-8
E_MANIFEST_INVALID imsmanifest.xml invalid See the message; rebuild with elabora build. LMS-8
E_UPDATE_BREAKS_RESUME This update will lose learner progress in the target LMS Publish as a new course/version in the LMS, or avoid structural changes. LMS-7
E_OBJECT_NOT_FOUND Free object folder not found Create objects/<id>/ with object.manifest.json, object.js, object.tests.json and object.notes.md (elabora object new).
E_OBJECT_ID_MISMATCH Manifest id differs from its folder Make the manifest id equal to the folder name.
E_OBJECT_PROP_DEFAULT Prop default invalid Every prop needs a default that matches its own schema.
E_OBJECT_TOKEN Unknown theme token Use an existing token of course.json theme.tokens or theme.custom (for example color.accent), or, for a material colour of the object (brass, wood), drop x-token and keep a literal default.
E_OBJECT_OBJECT_ID x-object-id refers to an undeclared object Declare the object in manifest objects.
E_OBJECT_TRACKING_OBJECTIVE Tracking objective not in planRefs Use an objective listed in planRefs.objectives, or add it there when the object does serve it (the plan says which objectives exist). A5
E_OBJECT_PLAN_MISMATCH Free object placed on a screen that does not serve its objectives Place it on a screen covering an item that lists one of its planRefs objectives. A1
E_OBJECT_CODE_MISSING_MOUNT object.js does not export mount export function mount(container, ctx) { … return { update, getState, setState, dispose }; }
E_OBJECT_FORBIDDEN_API Forbidden API in free object code Free objects run in a sandbox without network or storage: use host.asset() for files, host.emit() to talk to the course, props for settings.
E_OBJECT_NONDETERMINISM Non-deterministic call in free object code Use host.random(), host.now() and host.onFrame() instead of Math.random, Date.now and requestAnimationFrame, so tests can replay the object.
E_OBJECT_IMPORT Import not allowed Import only “three”, the allowed three/addons, “d3” and “@elabora/charts” (charts: D60), or relative files of the object folder.
E_OBJECT_PARSE object.js does not parse Fix the syntax error (ES2022 module).
E_OBJECT_TEXT_CONTRAST Free object text colour too close to its background x-text-on pairs a colour prop the object draws text in with the colour that text is read on (another colour prop or a theme token): change one of them until they reach 4.5:1 (WCAG AA). F1
E_OBJECT_STATE_BUDGET Persisted object state too large Lower persistState.maxLength or persist less state. LMS-3
E_CONTINUITY_DUPLICATE A continuity key used twice on one screen A key names one block per screen: the block that carries on to the next screen with the same key. Give the other block a key of its own, or remove its continuity.
E_CONTINUITY_MISMATCH Blocks sharing a continuity key are not the same kind Blocks with the same continuity key are one thing to the learner: give them the same type, and free objects the same object (props.object). Use another key for a block of another kind.
E_CONTINUITY_PLACE Continuity on a block that cannot carry on A continuity key goes on a block of a screen (with the blocks of its components’ slots), never on a block of a layer; a free object that carries on has no timing (its frame stays on the screen from one screen to the next). Remove the key, or the timing.
E_STYLE_RULE Stylesheet rule not allowed No @import and no external url(): reference files inside the course folder, such as theme/, assets/ or the component folder (packages work offline).
E_MATH_PARSE LaTeX error Fix the TeX between $…$ or in the math block (temml syntax, close to KaTeX). Write a literal dollar as $.
E_CHART_ITEM_DUPLICATE Two items of a chart with the same id Each item of a chart (a row, a part, a step, an event…) has its own id: highlights, voice beats and translations name items by id. Rename one of them; keep the id of an item that only moved.
E_CHART_ITEM_UNKNOWN A chart names an item it does not have highlight, a trend’s note, a diagram’s beat or label names an item by its id (a row, a part, a point’s x, a diagram node or edge): use one of the ids the message lists, or remove it.
E_CHART_DATA Chart data that cannot be drawn The message says what is missing. A trend needs at least two points whose x are all numbers in increasing order, or all distinct words; in predict mode, predict.from is the x of a point before the last.
E_DIAGRAM_TYPE Diagram type the diagram block does not draw The diagram block draws these Mermaid types: flowchart, sequenceDiagram, stateDiagram-v2, mindmap, timeline, journey, ishikawa-beta and venn-beta. Data belongs in a chart block (bars, donut, trend…); another kind of drawing in a free object.
E_DIAGRAM_SYNTAX Mermaid syntax error Fix the Mermaid text at the line and column the message gives; its first line names the type (flowchart LR, mindmap, sequenceDiagram…). elabora look --block <id> shows the drawing once it parses.
E_DIALOGUE_TARGET A dialogue goes to a node or an ending it does not have start, next (or a case’s go), an option’s next, an end and goto-dialogue name a node or an ending of the same dialogue by its id: use one the message lists, or add the node. elabora dialogue show <block> prints the dialogue with its node ids.
E_DIALOGUE_DUPLICATE_ID Two parts of a dialogue with the same id Node ids are unique in their dialogue, option ids in their node, ending and variable ids in their dialogue (a line id taken twice in the screen is E_NARRATION_LINE_DUPLICATE). Rename the new one; never an id learners already played (their saved path names options by node and id).
E_DIALOGUE_DEAD_END A dialogue node that may have nowhere to go A list of next cases is read in order and the first whose if holds wins: end it with a case without if (the way when none holds), or give the node an end.
E_DIALOGUE_SPEAKER A dialogue names a speaker the course does not have A line’s speaker, the dialogue’s learner and the cast name speakers of course.json speakers: add the character there (id, name, its voice, colour and look), or use an existing id. A line without speaker is a narration.
E_DIALOGUE_CONDITION A dialogue condition names what does not exist chosen names node.option, seen a node, var a variable of the dialogue (vars), variable a variable of the course, with a value of its type: fix the name the message gives. At run time such a condition holds, so the dialogue still plays.
E_DIALOGUE_VAR An option changes a variable the dialogue does not declare set and add change the dialogue’s own variables: declare it in vars (id and default), with a value of the same type; add takes a number variable. The course’s variables change on dialogue.ended, in an event of the screen.
E_DIALOGUE_ACTION An action a dialogue may not run Options and cues run presentation actions only: show-block, hide-block, show-layer, hide-layer, play-media, pause-media, set-object-props, reveal-step, play-sound, stop-sound. To change the course’s variables, navigate or complete the screen, write an event of the screen on dialogue.ended (or dialogue.chosen): replaying a path must never write the course’s state twice.
E_DIALOGUE_CUE A cue whose moment is not in its line A cue’s at names words of its own line ({ “word”: “Bonjour” }; line, when written, is that line): use words the line says, as written there, or remove the cue. Its text changed? Move the cue to the words that say the same thing.
E_GENERATOR Asset generator cannot be built Fix the syntax or the imports of the generator (see the message). Generators may import relative files and npm packages installed in the project.
E_STEP_UNREACHABLE Step that nothing reveals With continueRevealsSteps: false only the screen’s events reveal its steps: add a click event (a marker, a button) with { “type”: “reveal-step”, “step”: n } reaching this step, let Continue reveal the steps (remove continueRevealsSteps), or let the step open once answered (steps.<n>.opens “answered”, after an activity). A step that opens once answered needs an activity (quiz, numeric, decision, free object) in the steps before it.
E_COMPONENT_UNKNOWN Unknown block type Use a built-in type or the id of a component of components/ (elabora_list_components).
E_COMPONENT_ID Component id problem The id equals the folder name and is not a built-in type (heading, text, quiz…). Fork a built-in under a new id instead.
E_COMPONENT_EXTENDS Component parent problem extends.component must name an existing component without cycle. Video, audio and free objects are rendered by code: place them in a slot instead of forking them.
E_COMPONENT_SCHEMA Props schema of a component invalid props (or propsExtend) must be a JSON Schema of type object; x-kind is one of text, markdown, tex, asset, token; the keys of x-enum-labels (how the values of a choice read in the inspector) are values of its enum.
E_COMPONENT_TEMPLATE Template not allowed or broken Templates hold structure, decoration and bindings only: no script, style, iframe, form, link, media, event handler or external URL. Bind only declared props; data-each needs a list prop; buttons and inputs need a behaviour hook; images bind src to an asset prop and alt to a text prop (or alt=“”). See the components page (elabora docs components).
E_COMPONENT_HOOK Behaviour hook missing or misplaced A fork of quiz, numeric, decision or results keeps its behaviour: its template must provide the hooks listed in the message (elabora docs components), on the right elements. Behaviour hooks are not allowed elsewhere.
E_COMPONENT_SLOT Slot problem Declare every slot in component.json and mark it with an empty data-slot=“<id>” element (not repeated, not conditional); place blocks only in declared slots that accept their type.
E_COMPONENT_LEVEL Component used at the wrong level Screen-level components (level “screen”) are layouts: screen.layout. Block-level components are block types.
E_COMPONENT_PROPS Component props invalid Give values matching the props schema of the component (elabora_get_schema <component id>).
E_COMPONENT_FALLBACK Fallback produces invalid native blocks Fix the fallback templates of component.json: each item must give a built-in type and props valid for it once filled with the props.
E_COMPONENT_MIGRATION_PENDING Component instances need a migration The definition changed version and migrations.mjs has steps the instances have not been through: run elabora component migrate (MCP elabora_migrate_components).
E_COMPONENT_EXAMPLE Component example invalid Examples are checked like instances: fix the props of the example.
E_LOCKED Project locked by another writer Another Elabora tool (the app, a CLI command, the MCP server) is writing this project: run the command again in a moment. A lock left by a stopped process is broken automatically (at once on this computer, after 30 s from another one); delete the lock file named in the message only if no Elabora tool runs and it stays.
E_CONFLICT Files changed while the edit was computed Another program (an editor, an agent’s own file tools) wrote the files this edit touches at the same moment. Run the command again: it reads the files as they are now.
E_BLOB_MISSING Content of a binary file not kept The edit or the undo needs the bytes of a binary file that the blob store does not have and that the project no longer holds (the file changed or was deleted meanwhile). Run the command again; to bring a file back, restore it from a backup (elabora backup restore).
E_OP_TARGET_MISSING Edit target not found The file, key, element or anchor (after) the edit names is not in the project: it was removed or renamed meanwhile, or the id is wrong. Read the current state (elabora_get_screen, elabora overview) and give existing ids.
E_OP_DUPLICATE Element already in the list The list already holds an element with this id: choose another id for the new element, or move or update the existing one.
E_OP_NOT_KEYED List not addressable by id The edit selects an element by id in a list whose elements are not objects with distinct ids (or distinct strings). Fix the duplicate ids first (E_DUPLICATE_ID), or replace the whole list.
E_OP_NOT_JSON File is not a JSON document The edit changes a value inside a file that is not JSON or does not parse. Fix its syntax first (E_JSON_PARSE), or write the whole file.
E_OP_INVALID Invalid edit See the message: a block cannot move into itself, and ids are permanent (remove the element and add it again to give it another id).
E_PLAN_PERSON_ONLY A person’s decision on the plan Making a version of the plan and recording the client’s validation are the author’s: in Elabora (Plan › Versions) or in a terminal. An agent writes the plan, then tells the author it is ready to send.
E_PLAN_VERBATIM_LOCKED A text kept « à l’identique » is the author’s to change The client wants this text as signed: an agent never changes its words, its flag or removes it. Leave it as it is, or ask the author, who changes it in Elabora (the text, « Déverrouiller »).
E_CONVERT_REFUSED A block that does not fit the type it is converted into The message says what does not fit (too many items, a text too long, a picture missing). Shorten or complete the block first, or choose another target: elabora convert <screen> <block> –dry-run lists the possible ones.
E_GATE_SMOKE Gate 2 failed: mount/run/dispose See console errors in the message.
E_GATE_BEHAVIOUR Gate 3 failed: behaviour test Fix the code or, if the expected behaviour changed, the test (with a reason).
E_GATE_BUDGET Gate 4 failed: budget exceeded Reduce draw calls, triangles or textures, or raise the budget with a justification.
E_OBJECT_STRINGS Object strings of a block do not match the manifest props.strings only rewords strings the manifest declares (strings), with the same placeholders in braces: {gap}, {n, plural, …}.
E_OBJECT_ENUM_LABELS Words given for a value a setting does not take x-enum-labels (manifest) and props.enumLabels (block) say how the values of an enum read in the editor: each key is one of its values (numbers written as text). In a block, the keys of props.enumLabels are props with an enum, or <prop>.<field> for a field of a list’s items.
E_OBJECT_DECORATION Decorative object misused A decoration (pedagogicalRole “decoration”) only lives in theme.backdrop.object: it emits no events, keeps no state and takes no focus. A scene the learner uses or learns from is a free-object block with a role, plan objectives and a text alternative.
E_BACKDROP_OBJECT Backdrop object not usable theme.backdrop.object.id names a free object of objects/<id>/ whose manifest has pedagogicalRole “decoration”; its props must match the manifest.
E_BACKDROP_VARIANT Unknown backdrop variant A screen backdrop is “none” or a variant declared in theme.backdrop.variants (with its name and a one-line description).
E_GATE_VISUAL Gate 5 failed: snapshot differs from baseline If the change is intended, accept the new baseline with –update-snapshots.
E_GATE_CONTEXT_LOST Gate 5 not run: the WebGL context was lost before a snapshot The browser’s GPU process gave way, most often on a loaded machine; the test was run again and lost it again. Run the gates again when the machine is quieter; if it happens on a quiet machine, the object asks too much of the GPU (textures, draw calls, contexts).
E_GATE_A11Y Gate 6 failed: accessibility See the axe rule in the message.
E_LMS_API_NOT_FOUND SCORM API not found in this launch topology The runtime searches parents and the opener chain; report the topology if this happens with an Elabora package. LMS-6
E_LMS_DATA_LOST_ON_CLOSE Data lost when the window closed Commit earlier; nothing that is not committed before close survives. LMS-1
E_LMS_RESUME_FAILED Resume did not restore the learner position Check lesson_location and suspend_data handling. LMS-5
E_LMS_STATUS Unexpected lesson status See expected and measured values. LMS-13
E_LMS_STATUS_REGRESSION Status regressed A completed or passed status must never go back to incomplete. LMS-13
E_LMS_UNLOAD_LISTENER Content registers unload/beforeunload Remove it: unload no longer fires in Chrome and Edge; use visibilitychange and pagehide. LMS-1
E_LMS_SET_VALUE_REJECTED LMS rejected a value See the element and the SCORM error code. LMS-3
E_LMS_INITIALIZE_TWICE LMSInitialize called twice Never re-initialise a finished API (bfcache restore). LMS-5
E_LMS_NO_FINISH_ON_QUIT Quit did not call LMSFinish The Quit button must commit and call LMSFinish. LMS-1
E_LMS_SCENARIO Emulation scenario failed See the message.

Warnings

Code Title Fix Rule
W_SCREEN_FILE_UNUSED Screen file not listed in course.json Add it to a section or delete the file.
W_SYNC_CONFLICT_COPY File left by a sync service, not loaded Conflict copy (OneDrive, Dropbox, iCloud, Google Drive): compare it with the original, keep the right content in the original file, then delete the copy. Cloud placeholder: make the folder available offline so the file is downloaded.
W_MEDIA_NOT_OPTIMIZED Media file not in its master format Run elabora media optimize <path>: the file becomes a web master (MP4 H.264/AAC, M4A, WebP), its metadata (GPS positions of phones included) is removed and references follow a new extension. Bring new media in with elabora media import, never by copying files into assets/.
W_PLAN_DRAFT Plan not validated yet Fine for drafts and previews. The plan is written at any time (elabora plan write, MCP elabora_write_plan); before a client delivery, a person makes a version of it, sends it and records the client’s validation (Elabora › Plan › Versions, or elabora plan version then elabora plan approve --by "<name>"), and you build with –release. A5
W_PLAN_MODIFIED_SINCE_VALIDATION Plan changed since its validated version Fine while you work: the plan is written directly and its diff says what changed (elabora plan diff, the app’s marks); a release build lists the changes in its proof dossier and its result. To deliver them as validated, a person makes a new version, sends it and records the client’s validation. A5
W_PLAN_VERBATIM_CHANGED A text kept « à l’identique » changed since its validation The client wants this text as signed. If the author changed it deliberately, the next version holds the change and the client validates it; otherwise bring the validated words back (the app’s « Revenir à la V2 », elabora plan revert text:<id>). Agents never change it. A5
W_OBJECTIVE_NOT_PRACTISED Objective without practice or assessment Add a quiz, decision or free object linked to this objective (guardrail A2). A2
W_OBJECTIVE_VAGUE Objective is not observable Start with an action verb describing what the learner does (choose, diagnose, write…), not understand or know. A3
W_SPACING_MISSING No spaced retrieval planned Add plan.spacing (for example D+2, D+7, D+30) and deliver it through the LMS or emails. B5
W_BUSINESS_GOAL_MISSING No business goal in the plan Record the business outcome the course serves (plan.businessGoal). A4
W_NEUROMYTH Unsupported learning claim Learning styles and similar claims are not supported by evidence: propose an alternative to the author, who decides with the client. On a screen that names a myth to refute it, the author may ignore this finding until the words around it change; in the plan, it is the client’s (a waiver). E7
W_EXPOSITION_STREAK Too many screens without learner activity Insert a retrieval, decision or production activity (quiz, decision, free object) every few screens. B1
W_QUIZ_OPTION_COUNT Unusual number of options Three plausible options are usually best; avoid two-option items except true/false. A true/false question or a deliberate fourth distractor: the author may ignore this finding until the number of options changes. C1
W_QUIZ_ALL_NONE “All/none of the above” option Replace it with a plausible distractor. When the option is deliberate (the author judged it), the author may ignore this finding until the option’s text changes. C1
W_QUIZ_NEGATION Negative stem not highlighted Avoid negative stems or put the negation in bold. When the negation belongs to a quotation (a maxim, a source cited word for word), the author may ignore this finding (« Ignorer », or elabora ignore with its key): it comes back if the stem changes. C1
W_QUIZ_LENGTH_CUE The correct option is noticeably the longest Make options homogeneous in length and form. When the right answer must be precise and the distractors cannot be lengthened honestly, the author may ignore this finding until the options change. C1
W_QUIZ_NO_CORRECT Question without correct option Mark at least one option correct (or use a decision block for opinion questions). C1
W_TEXT_DENSITY Dense screen Slides: keep a screen under about 250 words; split it or move detail to an accordion or a layer. Scroll pages: break more than about 450 words of reading in a row with something to do (a knowledge check, an interaction, an accordion, a step), and split a page of more than about 1,500 words into two lessons. When the reading is the activity (a primary text, a source studied closely), the author may ignore this finding until the number of words changes. E3
W_DEAD_BUTTON Button without click event Add an event { on: { type: “click”, target: <block id> } } (with “name” for a named button: data-t-click=“name”) or remove the button (built-in button, or a component whose template has a data-t-click button).
W_DECISION_WITHOUT_CONSEQUENCE Decision without consequence Give each option feedback or an event (show a layer, go to a screen). D3
W_ACTIVITY_NO_FEEDBACK Fill-in or sort without feedback for wrong answers Write feedback.incorrect: the rule or the clue that leads to the answers, without giving them (they show in place after the last try); and feedback.correct: why the answer holds. D1
W_UNREACHABLE_LAYER Layer never shown Add a show-layer action or remove the layer.
W_COMPLETION_MISMATCH Screen completes before its activity Use completeWhen: “interactions-done” on screens with quizzes, decisions or free objects.
W_QUOTE_REPEATS Statement that repeats a text of its screen A statement (or a quotation) whose words are also in a text block of the screen reads twice, as a decorative pull quote does: say it once. Keep the statement for the one idea to remember and cut the sentence from the text, or keep the text and remove the statement. E4
W_COLUMNS_HIDDEN Block in a column that is not shown Columns with count 2 show the slots first and second only: move the block into one of them, or set count to 3.
W_ITEMS_MANY More items than the block shows well Past these counts a form of a block is hard to follow (D63): tabs over 7, a carousel’s steps over 7 (its intro and summary aside), markers on a picture over 8, cards over 12, a gallery’s carousel over 5 images. Split it into two blocks (two processes, two pictures), keep the items that matter, or choose a presentation that lists them (an accordion, a timeline). E3
W_TABS_LABEL_LONG Tab label too long A tab names its panel in one or two words, 24 characters at most, so that the tabs stay on one row and read at a glance: shorten the title, or choose the accordion presentation for longer titles.
W_HOTSPOTS_CLOSE Markers that overlap on a phone Two markers of an interactive picture are closer than their 44 px on a phone 375 px wide (x and y are shares of the whole picture): move one of them onto another point of its part, merge the two, or split the picture into two (a detail on its own picture). A focal point (focus) shows the picture half as large again on phones. F1
W_STEPS_SCROLL_SLIDES Scroll steps in slides A steps block in the scroll presentation (« Défilé ») follows the page as it scrolls; a slide does not scroll, so its steps show one under the other, each with its picture, and the slide may overflow. Choose presentation carousel, or pace the screen with its own steps (a block per step, step: n).
W_IMAGE_ALT_SUSPECT Alt text looks like a file name or a placeholder Describe the information, not the file. When the alt is right after all (a short name that is the information), the author may ignore this finding until the alt changes. F2
W_NUMERIC_AMBIGUOUS Misconception accepted as correct A misconception value lies within the tolerance of the answer: reduce the tolerance or change the misconception.
W_PLAYER_NO_WAY_BACK No way back in the player Enable Previous or the outline (elabora player . –enable previous), so that learners can go back to a screen they saw. Ask the author before ignoring it: it is fine when every screen has its own back buttons (a go-to previous event on a button).
W_PLAYER_END_UNREACHABLE Next hidden and the end out of reach Enable Next (elabora player . –enable next), or give each screen listed a way on that learners can reach: a button with a go-to event (next, or a later screen) in a step they see, and in slides steps that open by themselves (opens: “answered”) or by a reveal-step event. A narration that goes to the next screen by itself does not count: it stops on phones and for learners who choose « M’arrêter à chaque étape ». The details list the screens that lead nowhere.
W_PLAYER_AI_MENTION_HIDDEN AI mention hidden from learners Enable « IA et crédits » (elabora player . –enable credits): it says which voices, images or videos were made by an AI, as the EU AI Act asks (Regulation (EU) 2024/1689, article 50(4) and (5)), and it gives the credits CC-BY voices require. The transcript of a narrated screen still says « Voix générée par IA ». AI-50
W_PLAYER_CONTROLS_HIDDEN Narration without controls Enable the player’s controls (elabora player . –enable controls): learners must be able to pause a voice, read its captions and its transcript (WCAG 2.2 1.2.2, 1.4.2, 2.2.2; EN 301 549 9.1.2.2, 9.1.4.2, 9.2.2.2; RGAA 4.1 criteria 4.3 and 4.10). F3
W_PLAYER_TRANSCRIPT_HIDDEN Narration without transcript Show the transcript (elabora player . –set controls.transcript=true): learners who cannot hear the voice need its words in text (WCAG 2.2 1.2.1 and 1.2.3; EN 301 549 9.1.2.1, 9.1.2.3; RGAA 4.1 criterion 4.1). F3
W_PLAYER_EXIT_HIDDEN Quit hidden in an LMS package Enable Quit (elabora player . –enable exit): it saves and ends the session in the LMS, which otherwise ends only when the window closes (D3). A module for the web never shows it. LMS-1
W_SOUND_CREDITS_HIDDEN A sound’s credit hidden from learners Enable « IA et crédits » (elabora player . –enable credits): a CC BY sound must credit its author where learners can read it. CREDITS.txt in the package is for the LMS’s administrators, not for learners.
W_SOUND_DUCK_LOOP An ambience asked to lower the music Remove duck from the ambience: it is one of the sounds a duck lowers, and it plays for the whole screen. To hear it over the music, lower the music (its volume in sounds.background). duck is for a sound played once (no loop) that must be heard over the music and the ambiences.
W_SOUND_MUSIC_SWITCH_HIDDEN Music or ambiences learners cannot stop Enable « Affichage » (elabora player . –enable display): it has « Musique et ambiances », which learners switch off (WCAG 2.2 1.4.2: audio that plays by itself for more than 3 seconds can be paused or stopped). The player’s volume alone only shows on narrated screens. F3
W_RESOURCE_TYPE Resource in a format LMS servers may refuse Give learners the file as PDF, an office document, text, CSV, an image, audio, video or a ZIP: formats every LMS web server serves (IIS refuses unknown extensions). Zip a file of another kind. LMS-8
W_PLAYER_LOGO_CONTRAST Logo that would not read on its bar Put the logo on its light plate (elabora player . –set logo.plate=true), give the bar another colour (player.top.background), or use a version of the logo made for that background. Ask the author before ignoring it. measured is the best ratio of its colours on the bar, limit the ratio it needs (3); details give the bar (top or bottom), its token, its background and the logo’s file.
W_EVENT_NO_ACTION Event without action Give it what to do (do, or else when it has conditions), or remove it: an event without actions does nothing.
W_THEME_EFFECT_UNDEFINED Theme effect without its keyframes course.json theme.effects declares the effect: define @keyframes t-fx-<name> in the theme stylesheet (and t-fx-<name>-out for its going, otherwise it plays backwards). Until then the player fades.
W_TIMING_STEP Block anchored before its step opens Its timing.in falls in an earlier step’s stretch, but a block shows only once its step is reached: it comes when its step opens, not at the anchor. Anchor it to a line of its own step, or give it the anchor’s step.
W_TEXT_TOO_FAST Text shown too briefly to be read Learners need time to read what appears: about one second for 17 characters, 1.5 s at least (the message gives the time it stays and the time it needs). Keep the block longer (anchor its out later, or remove out), or shorten its text. A line that says more than 25 characters a second goes faster than most learners read its captions: say it slower (the voice’s speed) or cut it in two.
W_MOTION_LONG Movement longer than five seconds Effects of timed blocks run one into the other for more than five seconds (WCAG 2.2.2): learners can stop them with the bar’s Pause, but keep effects short and leave still moments between them, or let a step end in between.
W_STACK_UNTIMED Stack content without a moment Each content of a stack after the first comes at its own moment: give it a timing.in anchored to the word that brings it. Without it, it shows with the content before it, one over the other.
W_NARRATION_AUDIO_MISSING Narration line without audio Generate the voice (the voice tools) or import a recording: elabora narration import . <screen> <line> <file> (MCP elabora_import_narration) writes assets/narration/<language>/<screen>/<line>.m4a and its sidecar. Until every line of the screen has its audio, its timeline runs silent on estimated times, with its captions.
W_NARRATION_LINE_LONG A narration line that runs long A line is a few sentences, 5 to 20 seconds: past 45 s it is hard to follow, to time and to correct (the word aligner reads such a recording in pieces, and the whole line is made again for one changed word). Cut the text into several lines at its sentences, then make or import the audio of each. Nothing is blocked: a long line plays and is timed as any other. When the line is one breath on purpose, the author may ignore this finding until its audio’s length changes.
W_NARRATION_WORD_SWALLOWED A word the voice may have swallowed The word alignment found almost nothing of this word in the audio: listen to the line. If the word is missing, make another take (elabora voice generate . <screen> –line <line>) or record it again; a word said, even badly, is not flagged. A word said as a native speaker says it, almost swallowed, may be ignored by the author in the editor (« Ignorer », kept in course.json ignored for this word of this take): an ignored finding counts no more, and agents leave it alone; another take brings it back.
W_NARRATION_AUDIO_STALE Narration audio out of date The text, the audio file or the speaker’s voice changed since the audio was made (the message says which): generate or record the line again. Until then the voice says something else than the captions.
W_AUTO_ADVANCE Narrated screen that goes on by itself advance: “next-screen” plays the steps one after the other and goes to the next screen by itself: a time limit learners did not choose (WCAG 2.2.1). Prefer “auto” (the steps follow each other, then the screen waits for Next) or “learner” (the default: it stops at each step and waits for Continue); learners can still turn it into learner with « M’arrêter à chaque étape ». Keep it, waived in the plan, for a screen that must run on by itself (an introduction, credits). F1
W_SEGMENT_TOO_LONG Step of narration too long More than about 90 seconds of voice in one step without a pause for the learner (segmenting principle): cut the lines into two steps, so Continue paces them (elabora narration split . <screen> <line>: that line starts the next step), or move part of it to another screen. E3
W_NARRATION_DUPLICATED On-screen text repeats the narration Learners read and hear the same words at once, which loads them more than either alone (redundancy principle): keep the words in the voice and show keywords, a figure or a diagram instead (rule E4). The captions already give the text to those who need it. When learners should read along on purpose (a text studied, a quotation read aloud), the author may ignore this finding until the line or the block changes. E4
W_TIMED_INCREMENT Counting on a timeline cue Cues fire again each time playback crosses them (a learner who replays a step crosses them again): increment-variable on timeline.reached counts replays. Set a value (set-variable) instead, or count something the learner does.
W_NO_SCORED_ITEMS Pass/fail reporting without scored items Add scored quizzes (or scored decisions/objects), or report completed-incomplete. LMS-13
W_SUSPEND_DATA_NEAR_LIMIT Worst-case suspend data above 80 % of the LMS limit Leave headroom for future versions of the course. LMS-3
W_PACKAGE_LANGUAGE_LEFT_OUT A translation left out of the package of every language elabora build –languages all packages the translations whose texts are all translated and up to date and whose translated plan is approved (D59): the message says what this one lacks. Translate the texts it lists (elabora translate status . –to <lang>, MCP elabora_translation_status), have a person approve the translated plan (elabora translate approve), then build again; or build without it on purpose.
W_PACKAGE_TOO_LARGE_FOR_SOME_LMS Package larger than some LMSs accept, and no LMS chosen Choose the LMS: delivery.lms in course.json (elabora profiles lists them), or –profile; the build then checks its own limit. If it is one of those named, lower the media quality as the message says. LMS-8
W_PACKAGE_TOO_MANY_FILES_FOR_SOME_LMS More files than some LMSs accept, and no LMS chosen Choose the LMS: delivery.lms in course.json, or –profile. If it is one of those named, merge assets or split the course. LMS-8
W_COMPRESSION_RATIO_FOR_SOME_LMS Compression ratio above what some LMSs accept, and no LMS chosen Choose the LMS: delivery.lms in course.json, or –profile. If it is one of those named, store already-compressed data or split very repetitive files. LMS-8
W_PROFILE_TO_MEASURE LMS profile has unmeasured values Test the package in a real instance of this LMS and update the profile. LMS-15
W_WEB_IMAGE_WITHOUT_URL Sharing image without the module’s address Sharing previews (LinkedIn, Slack, Teams, Facebook) only read an image at an absolute address: build with –url and the address where the module will be served.
W_UPDATE_BREAKS_RESUME This update affects learners in progress See the per-LMS table: publish as a new version, or keep removed ids. LMS-7
W_OBJECT_LITERAL_COLOR Hard-coded colour in free object code Declare the colour as a prop (format color, x-control color) so authors can change it without code: bound to a theme token (x-token) when it carries the course identity, with a literal default when it is a material of the scene (brass, wood). A colour the object draws text in names its background with x-text-on. A5
W_OBJECT_PROP_CONTROL Editor control does not fit the prop x-control follows the type: text, textarea and asset for strings, color for a string of format color, select for a value with an enum (or an integer between a minimum and a maximum), slider (with minimum and maximum) and number for numbers, toggle for booleans, list for a list (type array with items), range for a low and a high number (two items with minimum and maximum, low first), vec2 for two numbers, vec3 and vec3-gizmo for three.
W_OBJECT_TESTS_MISSING Free object without behaviour tests Write object.tests.json (gate 3) before integrating the object.
W_OBJECT_NOTES_MISSING Free object without reviewer notes Write object.notes.md: its pedagogical role in two or three sentences for the client review.
W_OBJECT_PROP_UNUSED Declared prop never read by the code Read it from ctx.props/update(nextProps) or remove it from the manifest.
W_OBJECT_UNUSED Free object placed on no screen Place it with a free-object block on a screen covering the items it serves, or use a decoration as the course backdrop (theme.backdrop.object); otherwise delete its folder in objects/.
W_CONTINUITY_ALONE A continuity key on one block only Continuity carries a block on to another screen whose block has the same key: give that key to the matching block of the screen it should continue on (the previous or the next one), or remove it.
W_STYLE_LITERAL_COLOR Hard-coded colour in a stylesheet Use var(–t-…) tokens, or declare the colour in course.json theme.custom so a charter change (or an editor) can update it.
W_STYLE_FIXED_FONT_SIZE Font size in px Write font sizes in rem (px ÷ 16 at the reference window, 1600×900): 1rem follows the size classes of the player, so text gets smaller at 1280×720 and on phones with the rest of the design. clamp() with vw is fine when its bounds are in rem.
W_FONT_LICENSE_MISSING Font file without its licence next to it Put the licence of the font (OFL.txt, LICENSE.txt…) in the same folder as the font file: free font licences let a course embed a font when their text travels with it, and the build copies the licence files of that folder into the package. elabora font add brings a vetted font with its licence; for another font, elabora font add --from <@fontsource package folder or .tgz> or --file <font.woff2> --license <file> copies both. Check that the licence allows embedding (SIL OFL and Apache do).
W_STYLE_OVERRIDES_NESTED @layer overrides inside another rule Only the theme stylesheet’s top-level @layer overrides { … } blocks override the components (layer elabora.overrides). Inside @media or another rule it is a sub-layer of the theme and gives way to the components: put the block at the top level and the @media inside it.
W_STYLE_COMPONENT_OVERRIDDEN A component’s rule overridden by the theme Measured in the page (elabora look, elabora fit): a rule of the component’s stylesheet is overridden by a theme rule that does not name the component, so the component looks different in this course than its stylesheet says, and differently again once published to a library. In a course whose theme comes after the components (no theme.cascade), run elabora theme upgrade; then, or in an upgraded course where the theme rule sits in @layer overrides, move it out of the block if it is a course-wide default, or scope it so it leaves the component alone (:not(.t-layout--<id> *)). To restyle the component on purpose, write the rule in @layer overrides naming the component (.t-block--<id> …, .t-layout--<id> …).
W_STYLE_THEME_UNDER_COMPONENT A theme rule for a component that the component overrides Measured in the page: a theme rule that names a component (its .t-block–<id> or .t-layout–<id>, or its own classes) sets a property the component’s stylesheet sets too, and the theme’s rules come before the components (theme.cascade components-over-theme, D32), so it does nothing. To override the component from the theme, put the rule in the theme’s top-level @layer overrides { … } block; or change the component’s stylesheet, or a custom property it reads (var(--<name>, <default>)).
W_STYLE_TEXT Text written in CSS content: “…” cannot be translated or edited by authors: put the words in a block. I1
W_ASSET_SVG_TEXT Words inside an SVG figure Text inside an image cannot be translated, edited or reflowed on phones. Keep numbers, symbols and markers in the figure; put labels and legends in blocks next to it (a numbered list, a caption, a layout slot), or mark the image decorative. I1
W_IMAGE_INLINE_NOT_SVG Inline image that is not an SVG inline: true puts an SVG drawing in the page (for the draw effect and the theme’s CSS); a bitmap stays an <img>. Remove inline, or use the SVG version of the figure.
W_SVG_INLINE_SANITIZED Inline SVG with parts removed An SVG put in the page loses what is not safe there: scripts, event handlers, foreignObject, links and references to files or sites (only #fragments and data: images stay). Draw the figure without them (change its generator) so that the page shows what the file shows.
W_IMAGE_INLINE_HEAVY Heavy SVG put in the page An inline drawing is part of the course data every learner loads, on every screen’s first visit. Simplify it (fewer points, rounded coordinates, shared <defs> and <use>), or keep it as an image (inline: false) when it does not need the draw effect.
W_TIMING_DRAW_IMAGE Draw effect on an image the page cannot trace draw traces the strokes of the block’s own drawing. An image block shows an <img>, whose strokes the page cannot reach: set inline: true on the block for an SVG (local or generated). A bitmap has no strokes: use wipe or fade.
W_CHART_ORDER A funnel that widens A funnel shows what remains at each stage, so its values go down from top to bottom. Order the stages, use shape “pyramid” for levels that are not a flow, or bars to compare values.
W_DIAGRAM_COLOR Colours written in a diagram classDef, style and linkStyle lines are left out: diagrams take the course’s colours, so that every theme, dark ones included, stays readable. Remove them; highlight brings one node forward in the accent.
W_DIALOGUE_UNREACHABLE A part of a dialogue no path reaches No choice leads to this node or ending: link it (an option’s next, a node’s next, end) or remove it. elabora dialogue paths <block> lists what every path reaches.
W_DIALOGUE_LOOP A dialogue loop with no way out From these nodes no path reaches an end: give one of them an option (or a next case) that leaves the loop, or an end. Loops are fine as long as one way leaves them (a question hub with once options and a « Passer à la suite »).
W_DIALOGUE_OPTIONS_MANY More than four options in a decision Three options (good, ok, bad) are usually best: more slows the learner down and gives the right one away less than it dilutes it. Merge or remove some, or split the decision in two. A deliberate hub of questions may keep them: the author may ignore this finding until the options change.
W_DIALOGUE_OPTIONS_UNEVEN Options of very different lengths The longest option (button text) is more than two and a half times the shortest: learners spot it without thinking. Rewrite them to a similar length and form, or give the long one a shorter label.
W_DIALOGUE_LINE_LONG A line too long for a bubble A bubble reads at a glance: one or two sentences (under 280 characters). Split the line in two (two lines of the same speaker follow each other), or move the explanation to the option’s feedback.
W_DIALOGUE_SCORE_MISSING A scored dialogue misses what it counts scoring quality reads each option’s quality (good, ok, bad), points its points, ending each ending’s score: give them to every option (or ending) of the dialogue, or choose another scoring. An option without quality does not count in the quality score.
W_DIALOGUE_ENDINGS_UNCOVERED Endings that leave some scores without an ending With end: true, the first ending whose if holds is reached; when none holds, the dialogue ends without title. Put an ending without if last, or make the thresholds cover every score from 0 to 100 (the message gives the gap).
W_DIALOGUE_TREE A dialogue that only branches More than three decisions in a row branch without ever joining: each one multiplies the nodes to write (a fourth decision of three options adds 81). Let options join the common way (an option without next does), or bring branches back to a node they share.
W_DIALOGUE_NO_RETURN A practice dialogue that ends without a way back In practice mode the learner should see the other consequences once the first run ends: use revisit after-end (the practice default) or anytime, so the end offers « Changer ce choix » (in the debrief, or « Reprendre d’ici » on an answer) and « Recommencer ». For a test, use mode assessment.
W_CHARACTER_CONVENTION A character that does not follow the convention The player sets a character’s state on <g data-part=“character”> and shows its parts by their data-mouth, data-expression and data-gesture (docs/dialogues.md, characters): wrap everything that moves in that group, draw the four mouths (data-mouth=“closed|small|open|wide”, without data-expression), declare data-expressions (and data-default-expression among them) and data-gestures (name:seconds) on the root, and give each expression its parts. Copy the parts of a sample character and keep its tree.
W_CHARACTER_CONTENT A character holds what the convention forbids A page shows a character several times (the scene, an avatar): no id (so no gradients, clip paths, masks or filters; flat shapes instead), no text (its name is in the bubbles), under 40 KB. Remove them from the SVG.
W_DIALOGUE_LOOK An expression or a gesture the character does not have A character shows the expressions and plays the gestures its look declares: the expressions of its pictures (look.expressions), or its SVG’s data-expressions and data-gestures. Use one of those the message lists, or add it to the character’s look.
W_DIALOGUE_DECISION_CAP A dialogue path reaches the decisions cap A path stops after 60 decisions (a loop of next without end would be endless, and the learner’s saved path must fit the LMS). Give the loop a way out that every learner takes, or once options that run out.
W_GENERATED_ASSET_STALE Generated asset out of date Run elabora assets (MCP elabora_build_assets): the generator, a file it imports or a theme token changed since the asset was generated.
W_GENERATED_ASSET_EDITED Generated asset edited by hand Change the generator instead: the next elabora assets run overwrites the file.
W_STEP_ORDER Step out of reading order In scroll presentation each step appears below the previous ones: give this block a step at least equal to the blocks before it in the reading order (layout slots first, then block order), or move it.
W_STEP_SETTING_UNUSED Settings for a step the screen does not have screen.steps sets how steps open, keyed by step number: give settings only to steps that blocks of the screen carry, after the first one (the first step is shown from the start). A step that opens once explored (opens “explored”) needs, in the steps above it, an activity or a block with controls (a sequence, flip cards, disclosures, tabs…) that is not optional; otherwise use opens “continue”.
W_STEP_PLACEMENT Step on a nested block Steps apply to the blocks of the screen. Put the step on the component instance (its slots follow it) or remove it; blocks of a layer appear with the layer.
W_SLIDE_OVERFLOW Slide taller than the reference window At the reference size (presentation.fit.reference, 1600×900 by default) the screen scrolls. Split it into two screens, tighten the layout (side-by-side slots, smaller figures), or move secondary content to a layer or an accordion. A quiz reserves the room of its tallest feedback: feedbackStyle: "compact" shows the feedback of the chosen option without repeating its text (the message names the quizzes and what it saves). Steps do not save room in slides: they keep their place. elabora fit measures again in seconds. F1
W_SCROLL_ANIMATION_UNFINISHED Scroll animation that cannot finish Measured by elabora fit on scroll pages, with animations on: an animation driven by the scroll (animation-timeline: view() or scroll()) has not reached its end when the page is scrolled to the bottom, so the last blocks stay half faded, moved or turned. End its range sooner (animation-range: entry 0% cover 40%, rather than cover 100%), start it earlier, or leave room below the block. elabora look –scroll 100% –block <id> shows where it stops. F1
W_TEXT_CONTRAST_MEASURED Text hard to read over its background Measured by elabora fit against the pixels behind the text (backdrop, images, gradients), at the reference size and on a phone (375×812, down the page) with animations stopped: put the text on a panel (a background with enough opacity), dim the backdrop behind it (a variant for this screen), or change the text colour. WCAG 1.4.3: 4.5:1, 3:1 for large text. F1
W_PLAYER_BAR_WRAPS A bar of the player goes onto two lines on a phone Measured by elabora fit at 375×812: the items of the bar do not stand on one line (the Next button falls under the others). Give the bar fewer items (elabora player: progress is often the one to drop, the outline and the rail already say where the learner is) or shorter labels. F1
W_SLIDE_SHIFT Answering moves the slide In slides, an interaction must not push content around. The player reserves the room of activity feedback and keeps concealed blocks in place; what still grows is usually a component whose template opts out of the reserve, a free object asking for a new height, or text changed by an event. Reserve the room in the layout, show the content in a layer (presentation “panel” keeps the slide usable), or reveal it as a step. F1
W_RENDER_OVERFLOW Content wider than a phone screen At 375 px the screen scrolls horizontally: stack layout slots on narrow screens (container or media queries), give wide elements max-width: 100%, let tables and equations scroll inside their block. F1
W_COMPONENT_FALLBACK_LOSS Text not carried by the fallback Exports, text views and detach would lose this text: add the prop to the fallback of component.json. I1
W_COMPONENT_TEXT Words in a component template Words in a template cannot be translated or edited by authors: make them a prop, use a player label (data-t-label), or put them in a block of a slot. I1
W_COMPONENT_DECORATION Decoration exposed to screen readers Add aria-hidden=“true” to decorative SVG, or role=“img” with an aria-label bound to a prop. F1
W_COMPONENT_ID_ATTR Fixed id in a template Ids repeat when the component is used twice: write id=“name-{{@id}}” (and url(#name-{{@id}})), or rely on behaviour hooks.
W_COMPONENT_PROP_UNUSED Declared prop used neither by the template nor by the fallback Bind it in template.html or remove it from the props schema.
W_COMPONENT_UNUSED Component never used Place it on a screen or delete components/<id>/.
W_COMPONENT_DIVERGED Library component edited in the course This copy differs from the library version it came from: publish it back (elabora component publish), or fork it under a new id so later upgrades do not overwrite it.
W_UI_LABELS_LANGUAGE Player labels missing for the course language The player has labels in fr, en, de, es, it, nl and pt; in another language the missing ones fall back to English. Give every label in course.ui, with the placeholders of its English text: the message names the missing keys, and packages/player/src/labels.ts in elabora-core holds every key with its English text.
W_OBJECT_STRINGS_LANGUAGE Object words in another language than the course The manifest strings are written in its language; give this block the wording in the course language with props.strings (every key), or translate the course with elabora translate.
W_OBJECT_STRING_UNDECLARED Object code uses an undeclared string Declare every key read with ctx.t(key) in the manifest strings, with its text and a description for translators.
W_GATE_BOOT_SLOW Free object slow to start Return from mount() sooner: build the scene, render a first frame, then spread heavy work (procedural textures, large geometries) over the next frames with host.onFrame. Budget: budgets.bootMsMax (3 s by default, measured with software WebGL).
W_GATE_VISUAL_BLANK Gate 5: a baseline just recorded is a single colour The object drew nothing in that snapshot: a canvas sized from a container of no size, a WebGL context lost on a loaded machine, a drawing outside the frame. Look at the PNG; run elabora object test again on a quieter machine, or fix the drawing, then record it again with –update-snapshots.

Information

Code Title Fix Rule
I_FORMAT_OUTDATED Course in an older format, read migrated Run elabora migrate to write the migration listed in the message (one change after a backup version; elabora undo reverts it). Until then Elabora reads the course migrated in memory, and the first edit through Elabora migrates it.
I_EXTERNAL_LINK Link to an external site Fine for references; it opens in a new tab and needs network access.
I_MEDIA_PROCESSING Media file being converted A media job is writing this file (elabora media status); it appears when the job is done, and builds wait for it.
I_MEDIA_TOOLS_MISSING Media files not checked: ffmpeg not found Install ffmpeg (it includes ffprobe), or set ELABORA_FFMPEG and ELABORA_FFPROBE to the executables: media can then be checked, imported and converted.
I_PLAN_SOURCE_UNCITED Objective without source Link factual objectives to a source of truth (G1). G1
I_NUMERIC_NO_MISCONCEPTION Numeric question without misconceptions Add the values learners get with typical errors (wrong formula, inverted ratio, sign), each with feedback naming the error (guardrail D1). D1
I_GENERATED_MEDIA AI-generated media Listed for the AI Act article 50 transparency obligation; the player marks it. AI-50
I_PLAYER_SPEEDS_NONE Narration speed locked Offer 0.75× to 2× (elabora player . –set controls.speeds=0.75-2): learners who go at their own pace stay with the module; a locked speed meant to make them follow makes them drop out.
I_TIMELINE_WORDS_ESTIMATED Word anchors on estimated times The line has no word times yet (its audio has not been aligned, or it has no audio): word anchors are placed in proportion to its text. Align it: elabora narration align . <screen> (MCP elabora_align_narration); the voice tools and imports align the audio they write.
I_NARRATION_DIRECTIONS_IGNORED Stage directions the voice does not play Words in square brackets ([chuchote], [rit]) tell an expressive voice how to say a line (docs/decisions.md D29). The speaker’s voice in this language does not play them: it says the line without them, and learners never see them. Choose an ElevenLabs voice (Eleven v4) for this speaker to hear them, or leave them for later.
I_THEME_CASCADE_OLD The theme wins over the components (the cascade before D32) This course has no theme.cascade, so its theme still comes after its component stylesheets and overrides them whatever the specificity: a general rule of the theme (.t-figure img { width: 100% }) silently beats a component’s own rule for its images. Run elabora theme upgrade (MCP elabora_upgrade_theme): one undoable change that sets theme.cascade to components-over-theme and keeps the course’s look, the theme’s rules on properties the components set too going into a @layer overrides block. Then move out of that block the rules that are course-wide defaults.
I_SLIDE_SHIFT_MINIMUM Answering moves the slide at the minimum window At presentation.fit.minimum an interaction moves content. Check that the activity stays usable; see W_SLIDE_SHIFT. F1
I_SLIDE_OVERFLOW_MINIMUM Slide scrolls at the minimum window At presentation.fit.minimum (1280×720 by default) this slide scrolls a little. That is accepted for the smallest supported size; check that nothing important is cut and that the activity stays usable. F1
I_COMPONENT_SINGLE_USE Component used once A component pays off when reused. For a one-off look, a native block with a named style may be simpler to maintain.
I_COMPONENT_PARENT_CHANGED The parent of a fork has changed Review the parent changes; update extends.version once the fork is up to date.
I_GATE_VISUAL_OTHER_ENGINE Gate 5: baselines recorded for this browser, the object has another’s Snapshots are compared with the baselines of the same browser engine (fonts and WebGL draw differently). The object’s baselines were made with another engine: run elabora object test with that –browser to compare with them, or keep the new ones for this engine.
I_GATE_HUMAN_PENDING Human review pending (gates 7–8) Pedagogical review and code review by a person; the client sees props and notes, not code.

Rules

What each rule asks, as Elabora checks it (packages/core/src/diagnostics/rules.ts), and the codes that cite it.

Rule What it asks Codes
A1 Every screen, activity or question serves an item of the plan, and every item of the plan is covered by a screen (constructive alignment). E_PLAN_ITEM_UNCOVERED, E_PLAN_REFERENCE, E_LOCKED_TEXT_OUTSIDE_ITEM, E_PLAN_OBJECTIVE_UNUSED, E_OBJECT_PLAN_MISMATCH
A2 Each objective gets practice and an assessment at the same level as the objective. W_OBJECTIVE_NOT_PRACTISED
A3 Objectives are observable behaviours (an action verb, a condition, a criterion), never « understand » or « know » alone. W_OBJECTIVE_VAGUE
A4 The plan states the business goal the module serves; when the cause of a gap is not a skill, a performance aid may serve better than a course. W_BUSINESS_GOAL_MISSING
A5 The module follows the plan the client validated: the texts and questions it keeps are referenced, never copied, and what changed since the validated version is listed. E_PLAN_NOT_APPROVED, W_PLAN_DRAFT, W_PLAN_MODIFIED_SINCE_VALIDATION, W_PLAN_VERBATIM_CHANGED, E_PLAN_VERSION_INVALID, E_LOCKED_TEXT_NOT_USED, E_PLAN_QUESTION_NOT_USED, E_OBJECT_TRACKING_OBJECTIVE, W_OBJECT_LITERAL_COLOR
AI-50 Audio, images and video made by an AI are marked as generated (EU AI Act, article 50). I_GENERATED_MEDIA, W_PLAYER_AI_MENTION_HIDDEN
B1 No more than a few exposition screens in a row without something to retrieve, decide or produce. W_EXPOSITION_STREAK
B5 Spaced retrieval is planned after the module (for example on days 2, 7 and 30). W_SPACING_MISSING
C1 Questions follow item-writing rules: about three plausible options, no « all/none of the above », no hidden negation, homogeneous options, a correct option that is not given away. W_QUIZ_OPTION_COUNT, W_QUIZ_ALL_NONE, W_QUIZ_NEGATION, W_QUIZ_LENGTH_CUE, W_QUIZ_NO_CORRECT
D1 Each option of a question has elaborated feedback (why it is right or wrong, what to review), not only « correct » or « incorrect ». E_FEEDBACK_MISSING, W_ACTIVITY_NO_FEEDBACK, I_NUMERIC_NO_MISCONCEPTION
D3 A scenario’s feedback shows the realistic consequences of each choice. W_DECISION_WITHOUT_CONSEQUENCE
E3 Segmenting: media come in short parts the learner controls, and the text on one screen is bounded. W_TEXT_DENSITY, W_ITEMS_MANY, W_SEGMENT_TOO_LONG
E4 Redundancy: on-screen text does not repeat the narration said at the same time; captions can be switched on and off. W_QUOTE_REPEATS, W_NARRATION_DUPLICATED
E5 Signalling: headings and highlights show the structure, and key concepts come before complex content.
E7 No neuromyths (learning styles and the like); an agent points out those a request contains. W_NEUROMYTH
F1 No accessibility violation found by axe-core (WCAG 2.2 A and AA) on any screen or interactive state. W_HOTSPOTS_CLOSE, E_THEME_CONTRAST, E_HEADING_ORDER, W_AUTO_ADVANCE, E_OBJECT_TEXT_CONTRAST, W_SLIDE_OVERFLOW, W_SCROLL_ANIMATION_UNFINISHED, W_TEXT_CONTRAST_MEASURED, W_PLAYER_BAR_WRAPS, W_SLIDE_SHIFT, I_SLIDE_SHIFT_MINIMUM, I_SLIDE_OVERFLOW_MINIMUM, W_RENDER_OVERFLOW, W_COMPONENT_DECORATION
F2 What tools cannot judge is reviewed by a person (RGAA 4.1.2, WCAG 2.2): relevant text alternatives, reading order, keyboard use, target sizes. W_IMAGE_ALT_SUSPECT
F3 Every medium has captions or a transcript, and every meaningful visual a text alternative. E_IMAGE_ALT_MISSING, E_VIDEO_CAPTIONS_MISSING, E_MEDIA_TRANSCRIPT_MISSING, E_VIDEO_ALT_MISSING, E_OBJECT_A11Y_ALTERNATIVE, W_PLAYER_CONTROLS_HIDDEN, W_PLAYER_TRANSCRIPT_HIDDEN, W_SOUND_MUSIC_SWITCH_HIDDEN
G1 Every factual claim (a rule, a procedure, a figure) traces to a source of the client or an expert; otherwise it is marked to be checked. I_PLAN_SOURCE_UNCITED
I1 Words live in blocks, where authors edit them and translators find them: never in stylesheets, templates or figures. W_STYLE_TEXT, W_ASSET_SVG_TEXT, W_COMPONENT_FALLBACK_LOSS, W_COMPONENT_TEXT
LMS-1 The session ends without unload: the state is committed after every change and when the page is hidden, and Quit finishes the session. W_PLAYER_EXIT_HIDDEN, E_LMS_DATA_LOST_ON_CLOSE, E_LMS_UNLOAD_LISTENER, E_LMS_NO_FINISH_ON_QUIT
LMS-3 The learner’s state fits the suspend-data limit of each target LMS, in the worst case. E_VARIABLE_STRING_LENGTH, E_SUSPEND_DATA_BUDGET, W_SUSPEND_DATA_NEAR_LIMIT, E_OBJECT_STATE_BUDGET, E_LMS_SET_VALUE_REJECTED
LMS-5 A page restored by the browser or launched again initialises once and resumes where the learner was. E_LMS_RESUME_FAILED, E_LMS_INITIALIZE_TWICE
LMS-6 The SCORM API is found in every launch topology of the target LMSs (iframe, popup, nested frames). E_LMS_API_NOT_FOUND
LMS-7 An update keeps the progress of learners who started, or says which LMSs will lose it. W_UPDATE_BREAKS_RESUME, E_UPDATE_BREAKS_RESUME
LMS-8 The package is defensive for each target LMS: manifest at the root, portable file names, no external resource, size, file count, compression ratio and file types within its limits. E_FILENAME_NOT_PORTABLE, E_EXTERNAL_RESOURCE, W_RESOURCE_TYPE, E_PACKAGE_TOO_LARGE, E_PACKAGE_TOO_MANY_FILES, E_COMPRESSION_RATIO, W_PACKAGE_TOO_LARGE_FOR_SOME_LMS, W_PACKAGE_TOO_MANY_FILES_FOR_SOME_LMS, W_COMPRESSION_RATIO_FOR_SOME_LMS, E_LMS_UNKNOWN, E_FORBIDDEN_EXTENSION, E_MANIFEST_NOT_AT_ROOT, E_MANIFEST_INVALID
LMS-9 The package’s standard is one the target LMS supports. E_STANDARD_NOT_SUPPORTED
LMS-13 Status and score follow one state machine: a status never regresses, and pass/fail reporting needs a mastery score and scored questions. E_MASTERY_SCORE_MISSING, W_NO_SCORED_ITEMS, E_LMS_STATUS, E_LMS_STATUS_REGRESSION
LMS-14 Times are sent in the format the standard requires (cmi.core.session_time as HHHH:MM:SS.SS in SCORM 1.2) at every commit.
LMS-15 LMS profiles are executable facts with their sources: a value not documented is listed to be measured, never assumed. W_PROFILE_TO_MEASURE