QuickySitter works around several Second Life script-runtime limits but can’t eliminate them. This page catalogues the ones creators are most likely to hit.
Mono 64 KB script-memory cap
LSL scripts compiled with Mono have a hard 64 KB cap on combined code + stack + heap.
What QS does: Moves DATA_LIST and POS_ROT_LIST out of [QS]sitB’s memory and into LSD (qs:p:<ch>:<i>). At 1000+ pose entries, stock AVsitter pushes past the cap; QS reads on demand and stays slim.
What it still can’t fix: A single script’s own logic + globals + local-variable peaks still must fit in 64 KB. Very large [QS]adjuster configurations (deep ADJUST_MENU trees, many custom strings) can push adjuster past the cap. If you see Stack-Heap Collision errors in chat, check whether any script is consistently above ~55 KB used. (The fork moved the [DUMP] pipeline out of [QS]adjuster and into [QS]boot, which frees a chunk of adjuster heap, and adjuster now only kicks the cascade with a single 90098 message.)
LSD storage limits
Each linkset has a Linkset Data cap of 128 KiB total. Keys and values both count toward that byte budget, and there is no separate key-count limit. Values are stored as strings. A typical qs:p:* pose row costs ~75–80 bytes (key + value), so the pool holds roughly 1,700 poses if nothing else competes for it.
What QS does:
[QS]bootwrites the bulk ofqs:*keys exactly once per fresh seed, so the writes are batched and don’t hit the per-second write throttle.[QS]offsetchecksllLinksetDataAvailable()againstQPP_CFG:RESERVEandLSD_MIN_FREE_POSES × LSD_BYTES_PER_ENTRYbefore each LSD write; if free space is too tight, the offset goes into the RAM tier instead. See Personal Pose Offsets.
What it can’t fix: The pool is shared: qs:p:* pose rows, qs:prop:* prop records, QSO:* personal offsets and QuickyHUD’s QPP_CFG:* keys all draw from the same 128 KiB, so a pose-heavy build leaves less room for everything else. The 200-poses-of-headroom default for personal offsets is the practical safety margin.
Notecard size (65 536 bytes), per-line cap (1024 bytes) and the viewer editor’s paste cutoff
Two firm numbers, both from the SL wiki rather than from folklore:
- A notecard asset cannot exceed 65 536 bytes (Notecard). This is a storage limit, not a reading one: SL will not keep a larger notecard in the first place.
llGetNotecardLinereturns at most 1024 bytes per line, and drops the rest (llGetNotecardLine). It was 255 bytes until server 2021-10-25.565008, which is where the older figure in this documentation came from.llGetNotecardLineitself documents no total-size limit.
So “the script can read up to 64 KiB” was never quite the right framing: the 64 KiB is the largest notecard that can exist, and a long ANIM or PROP line loses its tail at 1024 bytes, not at 255.
The viewer’s built-in notecard editor has a second, lower limit, and it matters on the write side rather than the read side. The two measurements we have:
| Observed | What happened |
|---|---|
| 2026-05-16, pasting a 268 KB generated AVpos | Truncated on save at roughly 49 248 bytes. The last line that survived intact was POSE CooC08P11. |
| 2026-07-29, opening a 50 032-byte / 50 012-character production AVpos | Opens complete, down to the last line, and reads back fine. |
So a notecard of that size is not a problem to open. What is unverified is whether editing and saving one in-world near that size preserves it, since the truncation was measured on the save path.
Practical impact:
- Large AVpos notecards work at runtime. Nothing below the 65 536-byte storage limit constrains reading.
- Around 50 KB and above, prefer editing externally and pasting the whole content back (CTRL-A → CTRL-V) in one go rather than making small edits and saving in-world, until someone measures the save path properly.
- The symptom of having hit it: open the notecard, scroll to the end, and it stops mid-line.
- A bytes-per-pose-entry rule of thumb: roughly 80 – 120 bytes for a non-trivial entry with POS/ROT and a long animation name, so 65 536 bytes is somewhere around 550 – 800 entries.
- A single line only loses its tail past 1024 bytes, which in practice means a pose with a very long chain of animation names, or a
PROPline carrying worn-fit vectors on top of everything else.
Animation-loop drift between viewers
Multiple avatars in a SYNC pose can drift visually because the viewer determines loop phase locally at the llStartAnimation event, not from a network-wide source.
What QS does: [QS]sitA accepts LinkMsg 90271 to Stop+Sleep+Start every sitter’s main pose in the same Sim frame, re-phasing them. Policy (when to fire) lives in HUD scripts. See Re-Sync Protocol.
What it can’t fix: Two viewers running at very different framerates still won’t be pixel-perfect synchronized, and the re-sync just brings the drift back to a few frames. Aggressive re-sync intervals (e.g., every 5 s) help but cause visible “restart” flickers; 30 s is the practical sweet spot.
Permission-trigger races
PERMISSION_TRIGGER_ANIMATION is granted asynchronously. Between the sit event and the run_time_permissions callback, the script can’t play animations.
What QS does: [QS]sitA.run_time_permissions sequences the work: first request RAM-tier personal-offset push (90261), then play pose (90000). The race between the two is handled by sitA’s 90260 late-arrival re-apply.
What it can’t fix: If the viewer denies permission entirely (rare; some custom viewers have this option), the sitter sits without animation and the menu still appears, and there’s no way to re-request permission inside the same sit.
Region restart and asset-key changes
A region restart preserves LSD for prims in the region. A re-rez of a saved prim creates a fresh inventory key for the notecard.
What QS does: qs:boot:asset stores the notecard’s last-seen asset-key. On state_entry, boot compares against llGetInventoryKey("AVpos") and skips re-parse if they match, so live [HELPER] [SAVE] edits are preserved across region restart.
What it can’t fix: Detaching and re-attaching the prim, or transferring to a different owner who re-imports the notecard, gives a fresh asset-key and re-parses. This is by design, because you do want to read the latest notecard text if the owner edited it externally.
SL chat throughput
llSay / llOwnerSay / llShout are rate-limited per script per frame. [DUMP] of a large config can hit the limit and lose lines if dumped in a tight loop.
What QS does: [QS]boot’s dump cascade self-throttles via 90099 self-trigger between iterations, letting the Sim drain queued chat between batches. The output is also POST-uploaded to QuickySitter’s own self-hosted receiver at slquicky.com (URL in the chat) so a large dump can be fetched from a URL instead of scraped out of chat, subject to its own HTTP throttle (next section). The old avsitter.com service stopped accepting QS output and is no longer used (since boot 1.25, issue #66).
HTTP request throttle (the [DUMP] upload)
[DUMP] POSTs the rebuilt notecard to QuickySitter’s self-hosted receiver (slquicky.com/quicky-sitter/dump/settings.php) so a large config can be fetched from a URL instead of scraped out of chat. Outbound llHTTPRequest is throttled to 25 requests per 20 s per object (and 1000 per 20 s per owner).
What QS does: [QS]boot streams the upload in ~1 KB chunks (web() flushes once the escaped cache passes 1024 characters, one llHTTPRequest each) and paces them: between dump entries it arms a one-shot 0.2 s timer (QS_DUMP_PACE) instead of firing the next tick immediately, so the POSTs land well under SL’s ~1/s rate and never burst toward the 25/20 s cap. It also guards the throttle directly: llHTTPRequest returns NULL_KEY synchronously when a POST is refused, and boot sets dump_failed on that (and on any non-200 http_response), so the owner gets a [DUMP] Upload failed notice instead of a silently truncated link. boot never reads the response body, only the status, so the 2 KB response-body limit doesn’t apply, and the retrieval URL is built from the upload key.
What it can’t fix: The 25/20 s budget is per object, shared by every script in the linkset. If something else in the prim is also firing HTTP requests, even the paced dump POSTs can be refused under contention. Boot flags dump_failed and warns, but the refused chunk is lost and the uploaded copy is incomplete. Recovery: re-run the dump, or use the loud [HELPER] [DUMP], which also streams every line to local chat so you have the full text regardless of the upload.
SitTarget offset clamp
SL’s llSitTarget / llLinkSitTarget accept an offset relative to the prim’s pivot, clamped to ±300 m per axis; out-of-range values are rounded to the limit (see llSitTarget on the SL wiki).
Practical impact: none for normal furniture. The sit-target only controls initial docking; seated avatars are positioned by the pose engine via PRIM_POS_LOCAL, which is not subject to this clamp. [HELPER] arrow adjustments move pose positions, not sit-targets, so they aren’t limited by it either.
See also
- LSD Storage: the key layout that respects the 128 KB cap.
- Personal Pose Offsets: the LSD-vs-RAM tier decision.
- Re-Sync Protocol: the 90271 trigger for SYNC-drift.
- In-repo design docs:
PROTOCOL.md,STORAGE.md,test/TESTPLAN.md. - llHTTPRequest (SL Wiki): the authoritative outbound HTTP throttle and body limits.
