LERP Rive Documentation Errata Tracker
Last revalidated against the released runtime boundary: 2026-08-14 (2.40.0 Web line -> C++ runtime-v0.1.271; shader/GPU editor workflow remains Early Access only). Historical errata entries retain their original evidence dates.
Last editor-validated errata batch: 2026-08-14 (Rive Beta 0.8.5390 build 5377, MCP-driven Tests-protocol runtime validation plus current event-reference analyzer probe)
Initial errata tracker open date: 2026-04-26
Purpose: record LERP documentation inconsistencies, inaccuracies, and materially misleading gaps discovered while validating live Rive Editor behavior and current official Rive docs.
Rule for this file: only add an item when there is concrete evidence from at least one of:
- Rive Editor compiler/runtime behavior
- editor-validated live example behavior
- current official Rive docs
- local LERP docs contradicting each other
Status meanings:
confirmed: we have editor behavior or current official docs showing the LERP instruction is wrong/stale.gap: the LERP statement is not necessarily false, but is incomplete or misleading enough to cause wrong implementation.watch: likely issue, but needs one more editor validation or source check before treating as confirmed.resolved: issue was fixed in LERP docs; keep entry for traceability with date/hash note.
Summary
Entries are ordered newest first (freshest updates at the top).
| ID | Area | Status | Severity | Short finding |
|---|---|---|---|---|
| LERP-ERR-018 | Event names and gamepad payloads | resolved | high | Current-facing pages used historical *Invocation wrapper names, extra PointerEvent fields, and a stale generic gamepad payload instead of the Editor-reference event names and connected/event/disconnected triad. |
| LERP-GAP-017 | Runtime surface/editor type boundary | resolved | high | August 14 MCP validation records runtime passes for matrix equality and ranged GPUBuffer writes, the failed GPUTextureView format access, analyzer-only event/audio coverage, and the remaining Context/library/GPU/Web boundaries. |
| LERP-GAP-016 | While loops / script timeout recovery | resolved | high | Resolved in LERP on 2026-06-14 after a report from Rive Community user Avo: the submitted Exercise4_WhileCountdown file froze the Rive editor because its while energy > 0 do loop incremented steps but never changed energy, so init() never returned. Course now warns at the general while-loop section and inside the exercise itself. |
| LERP-ERR-015 | Path winding / fill rule | resolved | high | Resolved in LERP on 2026-06-12 after a report from GitHub user belal-sweileh: Exercise 3's described point order wound the triangle counter-clockwise, which the current clockwise-fill renderer does not draw; exercise reordered and winding rule documented. |
| LERP-ERR-011 | Node protocol | resolved | high | Resolved in LERP on 2026-06-12: draw was documented as required for add-menu listing; editor-validated that draw-less Node scripts list, place, and run. |
| LERP-GAP-012 | Node advance semantics | resolved | high | Resolved in LERP on 2026-06-12: documented the playback-vs-design-mode advance model — return false unsubscribes from the playback advance loop only, draw is independent, design-mode settle passes always pass seconds = 0 and ignore the return value. |
| LERP-ERR-013 | Vector deprecated usage | resolved | low | Resolved in LERP on 2026-06-12: glossary and environment exercise still taught deprecated vec:length() style despite the core-types deprecation table; switched to static Vector.* calls. |
| LERP-GAP-014 | Styling/Path API drift | resolved | medium | Resolved in LERP on 2026-06-12: PaintDefinition.gradient now typed (Gradient | false)?, Color.toFloat surfaced in core-types, Color documented as a raw packed number, Vector z/[3] documented, general path mutate-after-draw rule added, extract/positionAndTangent clamping and defaults documented. |
| LERP-ERR-010 | Exercise validator whitespace feedback | resolved | high | Resolved in LERP on 2026-06-04 after a report from Rive Community user Avo: failed-answer boxes now preserve exact whitespace and warn on whitespace-only mismatches. |
| LERP-GAP-009 | Script save/recompile workflow | resolved | medium | Resolved in LERP on 2026-06-04 after a report from Rive Community user Avo: first-script onboarding now explains the blue save-state dot and save-to-recompile behavior. |
| LERP-GAP-008 | Node script placement | resolved | medium | Resolved in LERP on 2026-06-04 after a report from Rive Community user Avo: docs now describe Node scripts as artboard script nodes and clarify nesting does not pass parent NodeData or PathData into callbacks. |
| LERP-ERR-006 | PropertyList API | resolved | medium | Resolved in LERP on 2026-05-12: list docs now use list.length + list[index] and include clear, removeAt, and removeAllOf. |
| LERP-ERR-007 | Runtime surface drift | resolved | high | Resolved in LERP on 2026-04-27: docs now include a pinned runtime compatibility baseline and corrected live/partial/not-exposed status for docs-labeled "Coming soon" APIs. |
| LERP-ERR-005 | Node pointer events | resolved | medium | Resolved in LERP on 2026-04-26: Node pointer-event docs now use event:hit() / event:hit(true) instead of boolean consume/propagate returns. |
| LERP-WATCH-004 | Property listeners | resolved | medium | Resolved in LERP on 2026-04-26: listener sections now warn to keep VM/property handles alive (or use anchored overloads) for long-lived listeners. |
| LERP-GAP-003 | ViewModel context | resolved | medium | Resolved in LERP on 2026-04-26: context:viewModel() wording now describes immediate data-context behavior, with context:rootViewModel() explicitly documented for root/global state. |
| LERP-ERR-002 | Path Effect / PathCommand | resolved | high | Resolved in LERP on 2026-04-26: Path Effect examples now use string command-name comparisons and clarify CommandType is not a guaranteed global table in editor scripts. |
| LERP-ERR-001 | ListenerAction | resolved | high | Resolved in LERP on 2026-04-26: ListenerAction guidance now uses performAction(self, listenerContext) as preferred and marks perform legacy. |
LERP-ERR-018 - Current Editor event names and gamepad triad
Status: resolved in LERP 2026-08-14
Severity: high
Reported by:
- MCP comparison against the live Rive Editor built-in
rive/artboardsandrive/interfacesscripting references
Affected local docs before fix:
docs/api/events.mdxdocs/quick-reference.mdxdocs/rive/protocols/listener-action-protocol.mdxdocs/rive/protocols/node-protocol.mdxdocs/rive/protocols/node-lifecycle.mdxdocs/rive/runtime-compatibility.mdxdocs/rive/script-capability-matrix.mdxdocs/rive/script-types.mdx
What was wrong:
- Current-facing event sections used the historical runtime wrapper names
KeyboardInvocation,TextInputInvocation,FocusInvocation,ReportedEventInvocation,ViewModelChangeInvocation, andNoneInvocationinstead of the current Editor namesKeyboardEvent,TextInput,FocusEvent,ReportedEvent,ViewModelChange, andNoneEvent. PointerEventclaimedpreviousPositionandtimeStamp, which are not fields in the current Editor reference;typewas documented as a plain string instead of the exactPointerTypeunion.- Gamepad guidance collapsed all payloads into stale
isGamepad()/asGamepad()/GamepadInvocationAPIs with anaxis0field. The current reference uses three distinct connected, changed, and disconnected payloads. ReportedEvent.delaySecondswas presented as current even though the current EditorReportedEventreference exposes no public fields. That property is evidenced only on the historical runtimeReportedEventInvocationwrapper.
Evidence:
rive/artboardsreturned the exactPointerType,PointerEvent,KeyPhase, event payload, gamepad field/method, andListenerContextdefinitions.rive/interfacesreturned the exact optional Node callbacksgamepadConnected,gamepadEvent, andgamepadDisconnected.- A temporary Tests script covering all of those types, fields, guards,
accessors, and Node callbacks recompiled with diagnostics
[]. The probe was removed; the original threeLERP_130_Runtime_Surface_Testscases still passed and final diagnostics remained clean. - Pinned
runtime-v0.1.262source confirms why older names exist:rive_lua_libs.hppandlua_listener_invocation.cppregister the historical*InvocationLua userdata wrappers, while that same source snapshot already implements the three-way gamepad surface.
Untested boundary:
- The analyzer probe did not synthesize keyboard, focus, reported,
view-model-change, or hardware gamepad events. It proves current Editor type
acceptance, not runtime dispatch or released Web
2.40.0behavior.
Fix implemented in LERP (2026-08-14):
- Replaced all current-facing event signatures with the exact Editor reference.
- Added full gamepad state/change fields, query methods, ListenerContext triad, and Node callbacks.
- Moved old
*Invocationnames into explicitly historical/source-runtime compatibility notes and removed unsupported current-facing fields. - Updated the compatibility matrix and changelog so analyzer acceptance, source confirmation, runtime dispatch, and released Web claims remain separate.
LERP-GAP-017 - August 14 runtime surface validation and editor type-check boundary
Status: resolved in LERP 2026-08-14 (was gap)
Severity: high
Reported by:
- MCP-driven live validation in a fresh Untitled composition, Rive Beta 0.8.5390 build 5377
Affected local docs before fix:
docs/api/core-types.mdxdocs/api/data-input.mdxdocs/api/data-values.mdxdocs/advanced/viewmodels.mdxdocs/rive/runtime-compatibility.mdx
Evidence:
- The real Tests-protocol script
LERP_130_Runtime_Surface_Testsrecompiled successfully with final diagnostics[]. Vector.xyz,Vector.cross3, vector buffer writes, andMat4.lookAt/Mat4.orthocomposition andwriteToBufferall passed.Mat2DandMat4equality passed live: identity matrices compared equal and translated matrices compared unequal.ViewModel1exposedfontProp: Property<Font>,imageProp: Property<Image>, andpayload: Property<Blob>. TypedgetBlob/getFont/getImagelookup, missing/null behavior, and Blob string/buffer/nilruntime writes passed after an explicitpayload :: anycast.- Before that cast, the current editor analyzer rejected the string, buffer, and
nilsetters withExpected this to be Blob. The course now teaches this distinction instead of presenting the runtime-accepted forms as unconditionally type-safe. Data.ViewModel1.new('name')returnednil;Data.ViewModel1.new()succeeded.GPUBuffer:write(source, destinationOffset, sourceOffset, byteLength)executed successfully for a valid range; both source- and destination-overflow probes were rejected.- The runtime executed
GPUBuffer/GPUTextureconstructors even though the current Editor analyzer reported those names as unknown globals. GPUTextureView.formatwas executed and failed withattempt to index userdata with 'format'.- A temporary exact-reference probe accepted the current event/gamepad surface and
AudioSound:pause(),resume(), andplay()with diagnostics[]; this is analyzer evidence, not runtime dispatch/call evidence.
Untested boundaries:
Context:globalViewModel()andContext:globalViewModelNames()were not executed.- Imported-library blob/shader resolution was not executed.
- Event/gamepad dispatch and the
AudioSoundtransport calls were not executed. - The broader GPUCanvas/render-pass/shader lifecycle was not executed and remains Early Access material. The ranged GPUBuffer operation is the narrow live exception;
GPUTextureView.formatis a recorded live failure, not an untested surface. - Released Web
2.40.0behavior was not established by this editor probe.
Why this matters:
The runtime source snapshot, editor analyzer, and runtime behavior do not form one undifferentiated availability claim. Learners need the editor-confirmed subset, the explicit Blob cast requirement, the narrow GPUBuffer pass, the GPUTextureView failure, and the still-unexecuted Context/library/broader-GPU/Web boundaries to remain visible when choosing APIs for a course exercise.
Fix implemented in LERP (2026-08-14):
- Added this traceable errata entry and linked it from the 1.3.0 changelog.
- Updated the core-types, ViewModel, data-value, and compatibility guidance with the Beta validation tier and the uncast Blob setter diagnostic.
- Preserved preview/rollout-dependent wording for released Web, Context, imported-library, and broader GPU surfaces while recording the exact GPUBuffer pass and GPUTextureView failure.
- Machine-readable validation evidence is retained with the 2026-08-14
release-suite run at
evidence/rive-editor/rive-editor-validation-2026-08-14.json; it is release evidence, not a public course route.
LERP-GAP-016 - while-loop exercise could freeze affected editor builds
Status: resolved in LERP 2026-06-14 (was gap)
Severity: high
Reported by:
- Rive Community user Avo, via LERP course report with frozen editor and unrecoverable
.revopen path
Affected local docs before fix:
/Users/ivg/github/lerp/docs/fundamentals/control-flow.mdx(Exercise 4 while-countdown exercise)/Users/ivg/github/lerp/docs/fundamentals/iteration.mdx(general while-loop warning was present, but did not mentioninit()startup blocking)
Evidence:
- Binary text recovery from the reported
ScriptCourse_Broken.revfound theExercise4_WhileCountdownscript fragments:
local energy = 3
local steps = 0
while energy > 0 do
steps += 1
end
print(`ANSWER: steps={steps},energy={energy}`)
- No recovered script fragment changed
energyinside the loop. Becauseenergystays3,energy > 0stays true forever,print()never runs, andinit()never reachesreturn true. - Local Rive runtime source includes a timed scripting context with a default timeout and wraps Lua calls through a guarded
pCall, so an editor freeze indicates an editor/runtime safety gap in the affected open/evaluation path rather than a normal recoverable script error.
Why this matters:
This is an easy beginner mistake in the exact exercise where students first practice while. In a vulnerable editor path, the result is not just a failed answer; it can make the editor or file open path unresponsive enough to require force quitting.
Fix implemented in LERP (2026-06-14):
- Strengthened the Fundamentals -> Iteration infinite-loop warning to explain that non-ending loops run synchronously inside the active callback, and
init()can block startup. - Added an Exercise 4 warning showing the exact unsafe loop shape and stating that the countdown variable must change inside the loop body.
- Added a checklist item requiring the loop body to change
energy.
Recommended upstream Rive fix:
- Ensure all user-authored Luau execution paths in the editor are covered by a watchdog or interrupt budget, including file open/recovery, script top-level evaluation,
init,advance,draw, listeners, converters, layout scripts, and path effects. - On timeout, mark the offending script asset or node as errored, skip it for the session, surface a diagnostic with the callback/script name, and keep the editor/file open.
- Provide an "open with scripts disabled" recovery mode for files saved with broken user scripts.
LERP-ERR-015 - Exercise 3 triangle wound counter-clockwise renders invisible
Status: resolved in LERP 2026-06-12 (was confirmed)
Severity: high
Reported by:
- GitHub user belal-sweileh (issue #2, 2026-05-19)
Affected local docs before fix:
/Users/ivg/github/lerp/docs/rive/protocols/node-protocol.mdx(Exercise 3 starter point order)/Users/ivg/github/lerp/docs/api/drawing.mdxand/Users/ivg/github/lerp/docs/quick-reference.mdx(no winding guidance)
Evidence:
- Live editor validation (Rive Early Access, 2026-06-12) with a side-by-side probe (
FillRuleProbe): the reporter's exact counter-clockwise triangle (top → bottom-left → bottom-right) rendered invisible while the clockwise twin rendered normally. - The Rive runtime ships a clockwise fill pipeline (
FillRule::clockwise; see runtime shader/pipeline docs), consistent with the observed behavior. - The scripting API exposes no fill-rule control on
PathorPaint(also answering the reporter's API question). - Follow-up object-model validation (same day): authored Fill components DO carry a
fillruleproperty (key 40, enumnonZero/evenOdd/clockWise) settable in the inspector — fill rule is per-Fill in the editor data model, while script-drawn paths (which have no Fill component) are fixed to the clockwise rule. Runtime probes confirmedpath.fillRulewrite throws,paint.fillRuleandPaint.with({ fillRule = ... })are accepted but silently ignored (Paint swallows unknown property writes), and a visual nested-contour ring test showed no even-odd effect. - Runtime-source confirmation (rive-runtime checkout, same day):
ScriptedPathData::renderPathhard-codesm_renderPath->fillRule(FillRule::clockwise)at render-path creation (src/lua/renderer/lua_path.cpp:29) with no setter; the Paint binding'spaint_set_valueswitch has nofillRuleatom andpaint_newindexignores the unknown-key return, which is why unknown Paint writes silently no-op (reported upstream — typos likepaint.thicknes = 4also vanish silently); the same function showsgradientaccepts any non-Gradient value as "clear" (sogradient = falseworks by falling through tonullptr); the same-frame path mutation rule is enforced with the literal error "Path was modified between draws in the same frame."; and Path Effect output paths inherit the host Fill's rule viapath->rewind(source->isLocal(), source->fillRule())(src/scripted/scripted_path_effect.cpp:48), making Path Effects the one scripting context governed by the authored fill rule.
Why this matters:
A beginner following the exercise exactly as written gets a compiling, running script that draws nothing — with no error pointing at winding order.
Fix implemented in LERP (2026-06-12):
- Exercise 3 point order changed to clockwise; winding warnings added to the exercise premise, the Path API reference, and the quick reference.
LERP-ERR-011 - draw incorrectly documented as required for add-menu listing
Status: resolved in LERP 2026-06-12 (was confirmed)
Severity: high
Reported by:
- Live editor validation (Rive Early Access, 2026-06-11): instrumented probe scripts placed and run via the Rive MCP
Affected local docs before fix:
/Users/ivg/github/lerp/docs/rive/protocols/node-protocol.mdx
Evidence:
- A Node script with only
initandadvance(nodraw) compiled with zero diagnostics, appeared in the add-to-scene menu, was placed as a script node (ScriptedDrawable), and raninit/advancenormally. - LERP claimed "If
drawis missing, the script will not appear in the add-to-scene menu" and quiznode-protocol-q1keyed "init and draw" as the required minimum.
Why this matters:
Learners building logic-only scripts (timers, orchestration) were told to add an empty draw, which adds an unnecessary per-repaint call; and the false claim misdirects debugging when a script "doesn't show up."
Fix implemented in LERP (2026-06-12):
- Requirements block, protocol table, AE/JS comparison row, common-mistake section, exercise premise, and quiz
node-protocol-q1updated:drawis optional and only needed for rendering.
LERP-GAP-012 - Node advance return semantics and design-mode clock undocumented
Status: resolved in LERP 2026-06-12 (was gap)
Severity: high
Reported by:
- Live editor validation (Rive Early Access, 2026-06-11): paired probe nodes (
advancereturningfalseafter 3 calls vs alwaystrue) instrumented with per-call prints, observed across design-mode interaction and ~10 s of playback
Affected local docs before fix:
/Users/ivg/github/lerp/docs/rive/protocols/node-protocol.mdx/Users/ivg/github/lerp/docs/rive/protocols/node-lifecycle.mdx
Evidence:
- Playback: the always-
truenode ticked at exactly 60/s with real accumulating delta; thefalse-returning node received zero advance calls while drawing ~600 frames in the same window — soreturn falseunsubscribes from the advance loop anddrawis fully independent. - Design mode: no advance loop and no clock exist;
advancefired as settle passes withseconds = 0on artboard-dirtying events (object moves, pointer over canvas, recompiles), and thefalsereturn was ignored across 200+ event-driven re-advances. - The Rive editor's own built-in example comment ("returns true if it needs to keep drawing") is contradicted by this behavior and was reported upstream.
Why this matters:
Time-based scripts that divide by seconds break at design time (seconds = 0); scripts that return false expecting drawing to stop are misdesigned; LERP previously never defined the Node advance return value at all.
Fix implemented in LERP (2026-06-12):
- Added the "Playback vs Design Mode: The Two advance() Clocks" section to node-lifecycle and an advance-semantics admonition to node-protocol, including the practical guard rules.
LERP-ERR-013 - Deprecated Vector instance methods still taught outside core-types
Status: resolved in LERP 2026-06-12 (was confirmed)
Severity: low
Reported by:
- Internal docs cross-validation against the editor scripting reference and
Vectordeprecation attributes (@[deprecated{ use = "Vector.*" }])
Affected local docs before fix:
/Users/ivg/github/lerp/docs/glossary.mdx(Vector entry usedpos:length()/pos:normalized())/Users/ivg/github/lerp/docs/rive/environment.mdx(exercise TODO useddiff:length())
Why this matters:
api/core-types.mdx deprecates all seven Vector instance methods in favor of static Vector.* calls; teaching the deprecated style elsewhere contradicts the course's own guidance.
Fix implemented in LERP (2026-06-12):
- Both occurrences switched to
Vector.length(...)/Vector.normalized(...).
LERP-GAP-014 - Styling and Path API reference drift vs editor scripting reference
Status: resolved in LERP 2026-06-12 (was gap)
Severity: medium
Reported by:
- Cross-validation of the editor's built-in scripting reference (
rive/paint,rive/color,rive/vector,rive/pathdefinitions) against LERP API pages, with runtime confirmation via Test-protocol scripts run in the Early Access editor (2026-06-11)
Affected local docs before fix:
/Users/ivg/github/lerp/docs/api/drawing.mdx/Users/ivg/github/lerp/docs/api/core-types.mdx
Runtime-confirmed findings folded into this entry:
PaintDefinition.gradientis(Gradient | false)?; assigningfalseremoves a gradient and also works on the livepaint.gradientproperty (reads backnil).Color.toFloat(color)exists (returns{r, g, b, a}in 0–1) but was only documented in the GPU shaders page; now surfaced in the core-types Color section.Coloris a plain Luaunumber(ARGB packed); raw literals like0xFFFF0000are valid and equalColor.rgb(255, 0, 0).Vectorhas a read-onlyzcomponent and[3]indexing (0for 2D vectors; populated by 3D APIs such asMat4:transformPoint).- The path mutation rule is general (any mutation after drawing requires waiting a frame), not just
reset();path:addaccepts anyPathData. positionAndTangentclamps distance and returns a normalized tangent;extractclamps distances andstartWithMovedefaults totrue.- Related upstream finding reported to Rive: the editor reference's
Paint.withexample usesColor.hex('#FF0066'), butColor.hexdoes not exist at runtime (type(Color.hex)isnil); LERP already usedColor.rgb(255, 0, 102).
Fix implemented in LERP (2026-06-12):
- All of the above documented in
api/drawing.mdxandapi/core-types.mdxwith editor-validation notes.
LERP-ERR-010 - Exercise validator feedback collapsed meaningful whitespace
Status: resolved in LERP 2026-06-04 (was confirmed)
Severity: high
Reported by:
- Rive Community user Avo
Affected local code before fix:
/Users/ivg/github/lerp/src/components/ExerciseValidator.tsx/Users/ivg/github/lerp/src/components/ExerciseValidator.module.css
User-reported evidence:
- In Fundamentals → Variables → Exercise 4, a submitted answer with extra spaces around the first pipe was correctly rejected by strict validation.
- The failed-answer display rendered the submitted string in normal HTML whitespace mode, visually collapsing the repeated spaces.
- Copying the displayed failed answer therefore produced a normalized-looking answer that could pass, making the original rejection impossible for the learner to diagnose.
Why this matters:
The validator must be strict enough to catch exact-output mistakes, but the feedback UI must show the exact submitted string. If the display changes whitespace, it can make a correct validation failure look arbitrary.
Correct guidance:
- Preserve exact whitespace in displayed submitted and expected answers.
- Warn learners when a failed answer only differs by spacing.
Fix implemented in LERP (2026-06-04):
ExerciseValidatornow detects whitespace-only mismatches after collapsed-whitespace comparison.- Answer display blocks now use whitespace-preserving styling.
- The failed-answer UI now warns that extra, missing, or tabbed spacing is the difference.
LERP-GAP-009 - First-script onboarding did not explain save-to-recompile
Status: resolved in LERP 2026-06-04 (was gap)
Severity: medium
Reported by:
- Rive Community user Avo
Affected local docs before fix:
/Users/ivg/github/lerp/docs/getting-started/your-first-script.mdx
User-reported evidence:
- Learners could paste or write a script, see the blue dot in the script tab, and then test without realizing the script had unsaved changes.
- Without saving, the script is not recompiled, so new code may not affect the running artboard.
Why this matters:
The first scripting exercise is where learners form their debugging model. If they do not know that save triggers recompilation, they can chase code mistakes that are really editor-state mistakes.
Correct guidance:
- The blue dot beside the script tab means unsaved changes.
- Double-clicking/renaming from the Assets panel can autosave, and Cmd+S / Ctrl+S saves explicitly.
- Saving recompiles the script and applies changes.
Fix implemented in LERP (2026-06-04):
- Added an early save/recompile warning to the first-script exercise.
- Added the save-state indicator screenshot.
- Updated the first-script assignment to include saving before validation.
LERP-GAP-008 - Node script placement wording implied host-shape code access
Status: resolved in LERP 2026-06-04 (was gap)
Severity: medium
Reported by:
- Rive Community user Avo
Affected local docs before fix:
/Users/ivg/github/lerp/docs/getting-started/your-first-script.mdx/Users/ivg/github/lerp/docs/getting-started/how-rive-scripts-work.mdx/Users/ivg/github/lerp/docs/rive/protocols/node-protocol.mdx/Users/ivg/github/lerp/docs/rive/protocols/node-lifecycle.mdx/Users/ivg/github/lerp/docs/rive/environment.mdx- Repeated exercise setup text across fundamentals, types, OOP, advanced, best-practices, and project pages
Local LERP evidence:
- Several lessons and project pages instructed learners to "attach" or "drag" a Node script to a shape or group.
- Other reference pages described Node lifecycle callbacks by protocol shape, not by a host-shape object, creating a misleading gap in the mental model.
Runtime source check used for the correction:
- Runtime source snapshot checked on 2026-06-04:
/Users/ivg/github/rive-runtimeata5e6bcf1(working tree dirty). scripted_object.cppcalls NodeinitwithselfandContext.scripted_drawable.cppcalls NodedrawwithselfandRenderer, with pointer callbacks receivingPointerEvent.lua_scripted_context.cppexposes context/data/assets/redraw methods, not an implicit parent-shape handle.scripted_path_effect.cppis the protocol that passesPathDataand host node data intoupdate.
Why this matters:
Learners could reasonably infer that nesting a Node script under a shape gives the script a special "this shape" API surface. That is not how the Node protocol is shaped. Nesting affects normal scene hierarchy behavior such as transform inheritance, opacity, and draw order; it does not pass parent NodeData or existing shape PathData into Node callbacks.
Correct guidance:
- Add a Node script to the artboard so Rive creates a script node.
- Position or nest that script node when hierarchy behavior matters.
- Use a Path Effect script when the code needs the existing path data of a stroke/fill.
- Use explicit references, inputs, or documented artboard lookup patterns when a Node script needs a specific scene node.
Fix implemented in LERP (2026-06-04):
- Added an early save/recompile note with the save-state screenshot in
your-first-script.mdx. - Reworded first-script and protocol setup steps from "attach to shape" toward "add to the artboard, position or nest the script node."
- Added Node placement boundary notes to the Node protocol, lifecycle, script type, scene API, environment, and capability matrix pages.
- Swept exercises and project pages for misleading attach/drag-to-shape wording.
- Corrected related Path Effect examples that implied Node scripts receive existing path geometry through
draw.
LERP-ERR-006 - PropertyList API docs were incomplete and inconsistent
Status: resolved in LERP 2026-05-12 (was confirmed)
Severity: medium
Affected local docs:
/Users/ivg/github/lerp/docs/advanced/viewmodels.mdx/Users/ivg/github/lerp/docs/api/data-values.mdx/Users/ivg/github/rive-runtime-docs/8.3-lua-api-reference.mdas a comparison source
Local LERP evidence:
advanced/viewmodels.mdxdocumentslist.countandlist:item(index).api/data-values.mdxdocumentslist.length,list:push,list:pop,list:shift,list:insert,list:swap,addListener, andremoveListener.api/data-values.mdxdoes not documentlist:clear().rive-runtime-docs/8.3-lua-api-reference.mddocuments.lengthand[index]access, notcount/item(index).
Validation note:
- This was validated using live examples in the Rive editor during the audit pass.
- Confirmed behaviors:
items:clear(),items:push(vm), and indexed iteration (items.length,items[i]) on a livePropertyList.
Why this matters:
The current list seeding pattern for editor-validation demos depends on clearing and repopulating a live list during init(). If LERP users follow the list.count / list:item(index) page, or cannot find clear(), they may implement list code that does not match the current editor/runtime API.
Correct guidance:
Use the current validated list surface:
local items = rootVM:getList("items")
if items then
items:clear()
local vm = Data.YourItemType.new()
-- set item properties
items:push(vm)
for i = 1, items.length do
local item = items[i]
-- read/write item props
end
end
Recommended LERP fix:
- Replace
list.countwithlist.length. - Replace
list:item(index)withlist[index]. - Add
list:clear()to thePropertyListAPI section. - Add a seeded Artboard List example using
Data.X.new(),list:clear(), andlist:push(vm).
Fix implemented in LERP (2026-05-12):
advanced/viewmodels.mdxnow useslist.lengthandlist[index].api/data-values.mdxnow documentsclear,removeAt, andremoveAllOf.- Related runtime baseline references were refreshed to the May 12, 2026 audit snapshot.
Validation reference:
- Live editor examples run during this errata audit (no internal project naming required in course docs).
LERP-ERR-007 - Docs "Coming soon" markers drift from runtime reality
Status: resolved in LERP 2026-04-27
Severity: high
Affected local docs before fix:
/Users/ivg/github/lerp/docs/api/events.mdx/Users/ivg/github/lerp/docs/api/system.mdx/Users/ivg/github/lerp/docs/api/data-input.mdx/Users/ivg/github/lerp/docs/rive/protocols/listener-action-protocol.mdx
What was wrong:
- Several surfaces marked "(Coming soon)" upstream were already live in runtime (
ListenerContext,KeyboardEvent,TextInput,FocusEvent,NoneEvent, etc.), but LERP did not expose a pinned compatibility mapping. - Some surfaces were documented as available in LERP without runtime status qualification (
Output<T>,ViewModel.name), despite not being exposed in current C++ Luau bindings.
Evidence baseline used:
- Runtime source gitHead (npm metadata):
5581955bf70d8976c60254de1a9c50c128e70582(runtime line2.37.4, published 2026-04-24 UTC) - Runtime release line (npm):
2.37.4for@rive-app/canvas,@rive-app/canvas-lite,@rive-app/webgl2, and@rive-app/canvas-advanced - Docs snapshot source:
https://rive.app/docs/llms-full.txt - Direct runtime binding checks in
listener_invocation.hpp,lua_listener_invocation.cpp,lua_input.cpp,lua_audio.cpp, andlua_properties.cpp
Fix implemented in LERP:
- Added
/Users/ivg/github/lerp/docs/rive/runtime-compatibility.mdxwith:- pinned runtime commit/date
- live/partial/not-exposed matrix for docs-labeled "Coming soon" surfaces
- repeatable re-audit workflow
- Updated affected API and protocol docs to align wording and examples to that baseline.
LERP-ERR-005 - Node pointer event consumption should use event:hit(), not boolean returns
Status: resolved in LERP 2026-04-26 (was confirmed)
Severity: medium
Affected local docs:
/Users/ivg/github/lerp/docs/rive/protocols/node-lifecycle.mdx
Local LERP evidence:
- The Pointer Events section says "Return true to consume an event, false to let it propagate."
- The same file later correctly says old
pointerDown(self, position: Vector): booleanis wrong andpointerDown(self, event: PointerEvent)is correct.
Why this is inconsistent:
- Current local API docs for
PointerEventdocumentevent:hit()as the way to mark an event handled. - Current Rive docs also document
event:hit()andevent:hit(true). - Live drag/drop validation used
event:hit()and no boolean return value frompointerDown/pointerMove.
Correct guidance:
Use:
function pointerDown(self: MyNode, event: PointerEvent)
if inBounds(self, event.position) then
event:hit()
end
end
Do not teach:
function pointerDown(self: MyNode, event: PointerEvent): boolean
return true
end
unless a specific legacy scaffold proves that path is still supported.
Recommended LERP fix:
- Replace the "return true / false" wording with
event:hit()/ no hit call. - Keep the warning that
pointerDown(self, position: Vector): booleanis an old pattern. - Add
event:hit(true)as the translucent/pass-through variant.
Validation reference:
- Live drag-node example validated in the Rive editor.
LERP-WATCH-004 - Property listener lifetime / GC warning is missing from LERP listener examples
Status: resolved in LERP 2026-04-26 (was watch)
Severity: medium
Affected local docs:
/Users/ivg/github/lerp/docs/api/data-input.mdx/Users/ivg/github/lerp/docs/advanced/viewmodels.mdx- any LERP examples that call
property:addListener(...)
Local LERP evidence:
data-input.mdxdocumentsproperty:addListener(callback)andproperty:addListener(obj, callback).- It does not explain why the object/anchor form matters.
- It does not warn that ViewModel/property handles obtained as locals can be garbage-collected while listeners are expected to remain active.
Current Rive docs evidence:
- Current Rive
PropertyTriggerdocs warn that if a ViewModel or property is obtained in a local and listeners are added without storing the object elsewhere, it may be garbage-collected after the function returns. - They recommend either storing the ViewModel/property on
selfor passing an anchor object toaddListener.
Validation impact:
A live coordinate-label script stores property handles on self:
self.xProp = vm:getNumber("x")
self.yProp = vm:getNumber("y")
self.zProp = vm:getNumber("z")
This is the safer pattern because the script adds listeners to those properties.
Correct guidance pending final validation:
When adding listeners to VM properties, prefer one of:
-- Option A: keep handles on self
self.vm = context:viewModel()
self.xProp = self.vm and self.vm:getNumber("x")
if self.xProp then
self.xProp:addListener(onChange)
end
or:
-- Option B: use anchor form when available
xProp:addListener(self, function(anchor)
-- ...
end)
Recommended LERP fix:
- Add a warning near every
addListenersection. - Explain when to store VM/property handles on
self. - Explain the anchor overload with a working example.
Validation reference:
- Live listener and drag examples validated in the Rive editor.
LERP-GAP-003 - context:viewModel() wording is misleading for nested/list item contexts
Status: resolved in LERP 2026-04-26 (was gap)
Severity: medium
Affected local docs:
/Users/ivg/github/lerp/docs/advanced/viewmodels.mdx/Users/ivg/github/lerp/docs/api/data-input.mdx/Users/ivg/github/lerp/docs/rive/protocols/node-lifecycle.mdx/Users/ivg/github/lerp/docs/rive/inputs.mdx
Local LERP wording:
advanced/viewmodels.mdxsays to usecontext:viewModel()for the artboard's main ViewModel.- The same page says
context:viewModel()gets the artboard's bound ViewModel. - The key takeaway says to use
context:viewModel()for artboard-level shared data. rive/inputs.mdxdescribescontext:viewModel()as global data shared across all scripts.
Why this is misleading:
A live editor validation depends on a more specific behavior:
- Inside an Artboard List item, the card-local script uses
context:viewModel()to get the item-local ViewModel. - The same script uses
context:rootViewModel()to get the root ViewModel. - That distinction is essential for list items. If
context:viewModel()is treated as always root/global/artboard-level, the focus action is designed incorrectly.
Current Rive docs evidence:
- Current
Contextdocs sayviewModel()returns the ViewModel bound to the node's immediate data context. - Current
Contextdocs sayrootViewModel()returns the root artboard data context.
Correct guidance:
Use this rule:
context:viewModel()
-> the ViewModel from the current node's immediate data context
-> in an Artboard List item, this is the item VM
context:rootViewModel()
-> the root artboard's data context
-> use this for root/global state such as selectedId or root lists
Recommended LERP fix:
- Replace "main/global/artboard ViewModel" wording with "immediate data-context ViewModel".
- Add an Artboard List example that reads an item VM with
context:viewModel()and root VM withcontext:rootViewModel(). - Avoid analogies like Redux/global context for
context:viewModel()unless clearly scoped to root scripts only.
Validation reference:
- Live Artboard List examples validated in the Rive editor.
LERP-ERR-002 - Path Effect examples use unavailable CommandType.* global
Status: resolved in LERP 2026-04-26 (was confirmed)
Severity: high
Affected local docs:
/Users/ivg/github/lerp/docs/rive/protocols/path-effect-protocol.mdx/Users/ivg/github/lerp/docs/site-map.mdxdescribes the Path Effects API as includingCommandType
Local LERP evidence:
- The Path Effect template compares
cmd.type == CommandType.moveTo. - Later examples compare against
CommandType.lineTo,CommandType.quadTo,CommandType.cubicTo, andCommandType.close. - The troubleshooting section repeats the same
CommandType.*pattern as the correct approach.
Editor evidence from live path-effect validation:
The path effect script threw errors including:
Unknown global 'CommandType'; consider assigning to it first
polygonPathEffectType 'unknown' does not have key 'type'
Cannot add indexer to table '{ read type: unknown }'
Current Rive docs evidence:
- Current Rive docs document command type values as
moveTo,lineTo,cubicTo,quadTo, andclose. - Current examples print
command.typeand show output likemoveToandlineTo. - The docs describe
CommandTypeas the type/category of a command, but the editor did not expose a usable global table namedCommandTypein this validation run.
Correct guidance:
Do not write this in editor scripts:
if cmd.type == CommandType.moveTo then
-- ...
end
Use the editor scaffold's actual type surface. In the currently validated path-effect workflow, compare against the string command names:
if cmd.type == "moveTo" then
path:moveTo(cmd[1])
elseif cmd.type == "lineTo" then
path:lineTo(cmd[1])
elseif cmd.type == "quadTo" then
path:quadTo(cmd[1], cmd[2])
elseif cmd.type == "cubicTo" then
path:cubicTo(cmd[1], cmd[2], cmd[3])
elseif cmd.type == "close" then
path:close()
end
Recommended LERP fix:
- Replace
CommandType.*examples with string comparisons unless Rive exposes an actual import/global in the current editor. - Add a note that
CommandTypein docs is a conceptual/API type name, not necessarily a global Luau table. - Add an editor-compile smoke test for every Path Effect snippet.
Validation reference:
- Live polygon Path Effect example validated in the Rive editor.
LERP-ERR-001 - ListenerAction callback is stale
Status: resolved in LERP 2026-04-26 (was confirmed)
Severity: high
Affected local docs:
/Users/ivg/github/lerp/docs/rive/protocols/listener-action-protocol.mdx/Users/ivg/github/lerp/docs/rive/script-capability-matrix.mdx/Users/ivg/github/lerp/docs/rive/protocols/transition-condition-protocol.mdxindirectly referencesperform(self, pointerEvent)as the ListenerAction callback
Local LERP evidence:
listener-action-protocol.mdxdefinesListenerAction<T>with requiredperform: (self: T, pointerEvent: PointerEvent) -> ().- The protocol table marks
performas required. - The knowledge check says the correct required callback is
perform(self, pointerEvent). script-capability-matrix.mdxlists ListenerAction required callbacks asperform.
Current Rive docs / editor evidence:
- Current Rive docs for
ListenerActionlist bothperformandperformAction. - They state that
performis deprecated and preferperformAction(self, listenerContext). - A live editor example was validated using
performAction(self: FocusWindowAction, _listenerCtx: ListenerContext).
Correct guidance:
Use this shape for new ListenerAction scripts:
function init(self: MyAction, context: Context): boolean
self.context = context
return true
end
function performAction(self: MyAction, listenerContext: ListenerContext)
-- action body
end
return function(): ListenerAction<MyAction>
return {
init = init,
performAction = performAction,
}
end
Do not instruct new work to use perform(self, pointerEvent) unless explicitly targeting a legacy scaffold.
Recommended LERP fix:
- Update the ListenerAction protocol page to show
performActionas preferred/current. - Mark
performas deprecated legacy. - Update quizzes and the capability matrix.
- Explain the difference between
PointerEventandListenerContext.
Validation reference:
- Live ListenerAction example validated in the Rive editor.
Source Links Checked
Official Rive docs checked during this errata pass:
- ListenerAction:
https://rive.app/docs/scripting/api-reference/interfaces/listener-action - Context:
https://rive.app/docs/scripting/api-reference/interfaces/context - Data Binding:
https://rive.app/docs/scripting/data-binding - PropertyTrigger:
https://rive.app/docs/scripting/api-reference/data-value/property-trigger - PathEffect:
https://rive.app/docs/scripting/api-reference/interfaces/path-effect - PathData:
https://rive.app/docs/scripting/api-reference/path/path-data - PathCommand:
https://rive.app/docs/scripting/api-reference/path/path-command - CommandType:
https://rive.app/docs/scripting/api-reference/path/command-type - Pointer Events:
https://rive.app/docs/scripting/pointer-events - PointerEvent:
https://rive.app/docs/scripting/api-reference/pointer-event - Docs machine-readable source for "(Coming soon)" diffing:
https://rive.app/docs/llms-full.txt - Node:
https://rive.app/docs/scripting/api-reference/node - Editor Data Binding Lists:
https://rive.app/docs/editor/data-binding/lists - Editor Scrolling:
https://rive.app/docs/editor/layouts/scrolling
Local LERP docs checked during this errata pass:
/Users/ivg/github/lerp/docs/rive/protocols/listener-action-protocol.mdx/Users/ivg/github/lerp/docs/rive/script-capability-matrix.mdx/Users/ivg/github/lerp/docs/rive/protocols/path-effect-protocol.mdx/Users/ivg/github/lerp/docs/api/data-input.mdx/Users/ivg/github/lerp/docs/api/data-values.mdx/Users/ivg/github/lerp/docs/advanced/viewmodels.mdx/Users/ivg/github/lerp/docs/rive/inputs.mdx/Users/ivg/github/lerp/docs/rive/protocols/node-lifecycle.mdx/Users/ivg/github/lerp/docs/rive/protocols/layout-protocol.mdx/Users/ivg/github/lerp/docs/rive/runtime-compatibility.mdx/Users/ivg/github/rive-docs/editor/data-binding/lists.mdx/Users/ivg/github/rive-docs/editor/layouts/scrolling.mdx/Users/ivg/github/rive-docs/editor/layouts/layout-parameters.mdx/Users/ivg/github/rive-runtime-docs/8.3-lua-api-reference.md- npm metadata check (
npm view @rive-app/[email protected] gitHead) returning5581955bf70d8976c60254de1a9c50c128e70582 - npm metadata check (
npm view @rive-app/[email protected] gitHead) returning2833de372c0d22596494c89c328008ce5b1106d7
Append Procedure
When a new inconsistency appears:
- Add it to the summary table.
- Add a detailed section with local source, observed failure, current correction, and validation evidence.
- Mark it
confirmed,gap, orwatch. - If the correction depends on current Rive docs, add the URL to Source Links Checked.
- If the item is later resolved in LERP, keep the entry and mark it
resolved in LERP <date/hash>.