Troubleshooting
This page is a directory of what Twill reports. Each message it writes is quoted below exactly as it appears in the Output, so pasting the line you are looking at into search lands you on its cause and its fix.
A bold entry is either a message quoted word for word or a symptom described plainly, and the paragraph under each one is the reason and what to do about it.
How to use this page
Section titled “How to use this page”- Have a message? Search this page for its text. The quote is verbatim, so a partial phrase is enough to find it.
- Have a symptom but no message? Find the section for the area you are in from the list below, then read down it; the symptom entries sit alongside the messages.
- Have neither? Start at When nothing here matches.
| Area | Covers |
|---|---|
| Installation and requires | Missing folders, server-only modules, silent no-ops |
| Boot and Lifecycle | Service discovery, Init and Start, critical failures |
| Player data | Sessions, saving, offline edits, migrations |
| Storage | What Store reports about keys and the DataStore itself |
| Networking | Declarations, handlers, rates, ranks, decoding |
| Replication | Subscriptions, patches, paths, published state |
| Permissions | Ranks, resolvers, group lookups |
| Admin console | Cmdr, the command gate, built-in commands |
| Monetization | Products, passes, receipts |
| Leaderstats | Bindings, value objects, sorting |
| Filtering | Text filtering and its failure mode |
| Studio and tooling | The Edit VM, API services, testing purchases |
Reading Twill’s output
Section titled “Reading Twill’s output”Every line carries the scope that wrote it, and anything at warning level or above also names the nearest line outside Twill.
[Twill.Data] (from MyGame.Services.Shop:42) main.Home for 123 holds Vector3; run it through Twill.Serialize.Encode first ^ who wrote it ^ who caused itThat second part is usually enough to skip opening a stack trace at all. When it is absent, the call came from inside the framework or through too many layers of native code to attribute honestly.
The default level is Info, so Debug lines are hidden. Raise it and the
framework says more, including full error traces from
Error.Install.
Twill.Log.SetLevel("Debug")Installation and requires
Section titled “Installation and requires”[Twill] ServerScriptService.Twill.Net is missing; the server half is not installed
ServerScriptService.Twill is absent or renamed. Both modules are required,
and the names matter because Twill finds its own server half by name.
The module named in the message is whichever one was needed first. See
Installing Twill.
[Twill] ServerScriptService.Twill.X is missing; ServerScriptService.TwillServer is from Twill 1, so replace it with ServerScriptService.Twill
A Twill 1 server folder is installed and the Twill 2 server module is not.
Install both modules from the release and delete TwillServer. See
Before upgrading.
[Twill] ReplicatedStorage.Twill is missing; install both halves from the same release
ServerScriptService.Twill was required, but the shared module beside it is
absent or renamed.
[Twill] ReplicatedStorage.Twill is X but ServerScriptService.Twill is Y; install both halves from the same release
The two modules come from different releases, usually after updating only one.
Replace both from the same .rbxm.
ServerScriptService.TwillServer is left from Twill 1 and is no longer read; delete it
Twill 2 is installed and working, and the old server folder is still there. Nothing reads it; delete it.
[Twill] 'X' is not an installed kit, or ..., or has no client half on a client
No kit under Kits answers to that name on this side. Check the spelling, and
that the kit’s halves sit in Twill.Kits in ReplicatedStorage and, for a kit
with server logic, in ServerScriptService.
[Twill] 'X' is not a Twill module, or is server only on a client, or
[Twill] 'X' is not a Twill module on the server
Either the name is misspelled, or you reached a server-only module from the client. Anything holding saved data, purchases, filtering, unpredictable draws, or signed secrets never exists on a client. The module reference marks which is which.
[Twill] Net.Handle is server only and the same for
Authorization.Configure, Authorization.SetRank, GetGroupStanding,
InGroup, Admin.Configure, Admin.Register, Admin.RegisterTypes,
Admin.Run
The module itself exists on the client, but this particular member does not. Reading a rank on a client is fine; deciding one is not.
Lifecycle.SetPlayerGate is server only
The client has no player pipeline, because there PlayerAdded means somebody
else joined.
Nothing happens at all, and there is no message
Nothing required Twill. A module that is never required never runs, which most often bites on the client: see the replication and admin console entries below.
Boot and Lifecycle
Section titled “Boot and Lifecycle”A service never boots, and nothing is reported
It must be a direct child of a folder passed to Start, must be a
ModuleScript, and must return a table. A module returning anything else is
skipped silently, which is what keeps a helper module sitting beside a service
from booting as one.
Check Lifecycle.GetBootOrder() for what was actually discovered.
'X' at Y is a folder; pass it to Start to boot what is inside it
Nesting a folder inside a service folder does not extend the search. Pass the
inner folder to Start as well:
Twill.Lifecycle.Start({ ServerScriptService.Services, ServerScriptService.Services.Combat,})duplicate service name 'X' at Y; skipped
Services are looked up by name, so names must be unique across every folder
passed to Start. The second one found is ignored.
failed to load X: ...
The module threw while being required, before any hook ran. This is ordinary Luau error: read the message after the colon.
'X' errored in Init: ... or 'X' errored in Start: ...
The hook threw. The rest of the boot carries on unless the service is marked
Critical.
SetPlayerGate called after Start; players already joined were not held
The gate was installed too late to hold the players already on the server. Set
it during Init.
Start called more than once; ignoring
Lifecycle.Start runs once per side. If you need more folders, pass them all in
one call as a list.
A service sees another service that is not ready
You called it from Init. Move the call to Start, which runs only after every
Init has finished.
A Start hook depends on another Start having finished, and sometimes fails
Each Start runs on its own thread, so boot order decides when one begins,
never the order in which they finish. Have the later one ask for what it needs
rather than assume it exists.
Lifecycle.Get has no service named 'X'
Lifecycle.Get was given a name that was never discovered. Usually a typo, and
occasionally a service that failed to load earlier in the same run.
Everyone is kicked with This server failed to start.
A service marked Critical threw in Init or Start. The reason is in the
kick message and in Lifecycle.GetFailure(). Players arriving afterwards are
kicked on sight until the server is replaced.
boot failed: ... on the client, and nothing else runs
The same failure on the client, where there is nobody to kick. The client boot stops there.
Player data
Section titled “Player data”Players are kicked with Your saved data could not be loaded.
The session would not open. Usually the DataStore API is having trouble, or a
migration step threw. Look for the [Twill.Data] lines above it.
Players are kicked with Your data session was claimed by another server.
Normal when someone changes servers faster than the old session is released. Their branches are freed at the same moment.
Players are kicked with This server failed to load your session.
The player gate itself threw, rather than the session failing to open. If the
gate is Data.Gate, the cause is above it in the log; if it is your own gate,
the error is in it.
Data.Gate used before Configure
Lifecycle.SetPlayerGate(Data.Gate) ran before Data.Configure. The same
message exists for GetOffline, Edit, and Reset.
Data is already configured
Configure runs once. Configuring twice would change the shape of stored data
underneath a running server.
a branch cannot be named 'main'
main is the scope name for the primary profile, so a branch cannot take it.
Data has no branch named 'X'
The name does not match anything in Branches. Data.ListBranches() reports
what exists.
Data.Edit answers "unsupported", with X.Y for 123 holds Z; run it through Twill.Serialize.Encode first
The value holds something a DataStore cannot store. Encode it, or fix the shape of its keys. See Store Roblox values safely.
Data.Edit answers "unknown"
No scope answers to that name. The primary profile is "main", not
"Data"; Data is the replication key, which is a different thing.
Data.Edit answers "blocked"
Something along the path is held by a value that is not a table, so the write would have to overwrite it. Nothing was written.
Data.Edit answers "queued" and the change never lands
That is the truth rather than a fault: the user is not on this server, so the edit waits for a server that holds them. For a user who never returns, it never lands.
applied a queued edit to 'X'
Informational. An edit aimed at this player from elsewhere has arrived.
dropped a queued edit to 'X': refused
An edit sent from another server arrived, but the scope’s Validate check
refused the result, so nothing changed. blocked in the same place means a step
along the path is not a table.
an edit to 'X' in 'Y' was refused, so nothing changed: ...
Data.Edit or Data.Reset tried the change on a copy, and Validate refused
it. The call returned "refused", and the live data is untouched.
could not read 123: ... or stored data for 123 could not be upgraded: ...
GetOffline failed to read, or the stored data failed a migration. It answers
nil rather than a partial profile.
could not open branch 'X' for 'Y'
The branch session would not open. Every caller waiting on that load is answered
with nil rather than left waiting.
stored data is at version N, past the M this server upgrades to; its version is left alone
The profile was written by a newer server than this one. It is read as it stands and its version is not moved backwards. Roll the place forward rather than migrating down.
Data changes are not saving
Check three things in order: that you mutated the table Data.Get returned
rather than a copy of it, that Data.IsReady(player) is true, and that Studio
Access to API Services is enabled.
'X' migration to version N failed: ...; their stored data was left exactly as it was
A migration step raised. The player was kicked, and the steps ran on a copy, so nothing they had is lost or half converted. Fix the step, and the next load runs it again from the version the data carries.
storage cannot be reached from this Studio session (...); player data lives in memory ...
Studio Access to API Services is off, or Studio is offline. Players load from the template, and nothing is saved when the session stops.
Storage
Section titled “Storage”These come from Store, underneath Data. Most of them
name a key rather than a player.
'X' was taken again here, so what was held before it can no longer be written
The same key was opened twice on this server, and the earlier handle is now inert. Whatever held it should let it go; the newer session owns the key.
'X' in 'Y' was not written, and keeps what it held before: Validate refused it: ...
The store’s Validate check refused what the key holds, so the save was skipped
and the last good data stays stored. A check that raised reads
Validate raised an error: .... Until the data passes again, no later save
lands either, so find what put it in that state.
'X' in 'Y' was not written, and keeps what it held before: 'F' holds ..., which storage cannot keep
The data holds a value a DataStore cannot store, at the field named. The save
was skipped before storage was asked, and the last good data stays stored. No
later save lands until the value is gone. Encode it with
Serialize or remove it.
'X' in 'Y' holds N of the 4194304 characters a key may hold; storage refuses a write past that
The key is past 3,000,000 characters. Saves still land, but one past the limit
fails, and every save after it. Trim what the key holds, move part of it to a
branch, or turn Compress on for the store.
'X' in 'Y' could not be written: ...
A save was refused, and the reason says which of the two applies: another server holds the key now, or the key no longer holds anything this store wrote. Neither is retried, because retrying would write over whoever holds it.
'X' could not be taken within N seconds
The session did not open inside StartTimeout. The usual cause is a server that
has not yet released the key, and the usual outcome for a player is the load
failing rather than waiting longer.
'X' holds something this store cannot read, and was left alone
The key holds a value that is neither a Twill envelope nor a ProfileStore one.
Nothing is overwritten, because overwriting is how data is lost. Read it with
playerdata versions before deciding what it was.
'X' could not be packed to be written, so it was not taken
Compress is on for the store and the data could not be packed. The key is
left as it was. Look for a value Compress refuses, such as a cyclic table.
storage is failing repeatedly; the last of it was '...'
The DataStore has refused several requests in a row. Twill backs off and keeps trying. Check the Roblox status page before changing anything.
storage cannot be written from here (...); nothing will be saved
The reach probe answered that this place cannot write. In Studio this is Studio Access to API Services being off.
storage never said whether it could be reached; carrying on as though it can
The probe itself did not answer in time. Saving is attempted anyway, because refusing to try is worse than trying and failing.
N key(s) were still being written when this server closed
Shutdown ran out of patience with writes still in flight. Those writes may or may not have landed. It points at a save that takes too long, usually a profile that has grown.
Networking
Section titled “Networking”'X' was already declared as (...) and cannot be redeclared as (...)
Two places declared the same remote with different types. Make them agree. This refusal is what stops one caller from serialising through another’s types.
Net.Get has no remote named 'X' yet
Net.Get ran before whatever declares that name. Declaring is idempotent, so
the usual fix is to declare it in a shared module both sides require.
'X' already has a handler
One handler per remote. Net.IsHandled lets a module check rather than claim
and be refused.
'X' replies to the caller, so it needs a Reject option
A remote that replies must say what a refused caller is told, otherwise a refusal leaves them waiting forever.
Rate for 'X' must be above zero
Metering always applies. A rate of zero would refuse everything, so it is rejected as a mistake.
Calls are silently dropped, and the log says 'P' is over the rate for 'X' (N call(s) refused)
The caller exceeded the remote’s rate. Refusals are reported at most once every few seconds per player and remote, with a count, so the log cannot become an amplifier for the flood it is refusing.
'P' lacks the rank for 'X' (N call(s) refused)
MinimumRank refused them, before any of their allowance was spent.
A refusal naming a field, such as 'P' Stats.Coins should be a whole number for 'X'
The Schema rule for that argument did not match. The reason names the position
that failed.
validator for 'X' errored: ...
Your Validate threw. A test that cannot decide is read as a refusal, never as
consent.
handler for 'X' errored: ...
Your handler threw. A remote that replies answers with Reject; one that does
not drops the call. Either way the failure never reaches the calls behind it in
the same message.
'X' was declared here but the server never declared it; calls on it go nowhere
A name declared on this client that no server module declares. Calls on it are dropped locally rather than reaching the wire. Usually a misspelling, or a shared remotes module the server never requires.
'X' was called before the network was up more often than it holds
Calls made before the wire ids arrive are held and sent once they do, and that hold has a ceiling. Reaching it means a client is calling a remote far ahead of the network being ready.
an unreliable call was larger than one unreliable message carries, and was dropped
An unreliable remote was given more than fits in a single unreliable message. There is no second chance for one of those, by definition. Send less, or declare the remote reliable.
a call this side could not read
A call arrived that the declared types could not decode. The call is dropped and the ones behind it in the same message still arrive. From a client this is ordinarily somebody probing the remote; between your own two sides it means the declarations have drifted apart.
a remote is listened to on a client; the server serves one with Net.Handle ...
Remote:Connect, Once, or Wait was called on the server. A server listener
would receive calls with no metering. Serve the remote with Net.Handle.
a call could not be written (N time(s)): ...
A value did not fit its declared type, and the call was dropped at the sender. The rest of the message is unaffected. The reason names the field.
Replication
Section titled “Replication”The client never receives anything
The client announces itself the first time its half of the module is required.
If no client code ever requires Twill.Replication, the server has nothing to
send to. Requiring it once anywhere in your client boot is enough.
the server never registered replication; nothing will arrive
The client waited for the server to declare the replication remotes and gave up.
The server half never loaded, which usually means the server never required
Twill.Replication either.
patch arrived for 'X' before its value did; ignored
A change arrived for a key this client has never held. Applying it would build a value the server never published. In practice it means the readiness signal was missed rather than a message being lost.
'X' could not be sent to Y (N time(s)); it goes again on its next write
The key’s value could not be written to the wire: it holds something
Types.Any cannot carry, such as a function, or it
is past the server to client bounds. The player keeps what they last received.
Every other key still arrives.
A subscription never fires
Check whether the key name contains a dot. The first dot separates the key from
the path, so a key called "Player.Data" is read as key Player, path Data,
and can never match.
path 'X' inside 'Y' is blocked by a non-table
A step along the path is held by something that cannot be descended into.
Nothing was written, and SetPath answered false.
'X.Y' is not a number
Increment found something other than a number at the path. A missing value is
fine and counts from zero; a string is not.
validator for 'X' refused a write or validator for 'X' errored: ...
The key’s guard rejected the value, or threw and was read as a rejection. Clearing a key is always allowed regardless.
OnChanged("Data") fires constantly
That is the behaviour when Replicate is configured: the view is rebuilt on an
interval. Network traffic is unaffected, because a message is only sent when
something moved. To hear real changes, subscribe from the client.
A value read on the server does not match what the client has
Something wrote into the value returned by Get or GetFor. Those hand back
the published value itself, not a copy. Publish through Set, SetPath, or
Mutate instead.
Permissions
Section titled “Permissions”Everyone reads as rank zero
Authorization.Configure has not run, or ran after the check. A player whose
rank has not been decided reads as the lowest, so a check made too early refuses
rather than admits.
Authorization is already configured
Configure runs once, so that who is privileged cannot change while the server
is running.
Resolve errored for 'X': ...
Your resolver threw. The player keeps the rank Users or Default already gave
them.
could not read group 123 for 'X': ...
The group lookup failed. It is not remembered, so it is retried rather than
settled wrongly. Treat nil from GetGroupStanding as unknown, never as “not a
member”.
A promotion does not survive a rejoin
SetRank lasts for the session only. Write it to Data and
read it back in Resolve to make it permanent.
Admin console
Section titled “Admin console”F2 does nothing
Nothing loaded Cmdr. It takes two requires: a server one that calls
Twill.Admin.Configure, and a client one that requires
@game/ReplicatedStorage/Twill/Admin by path.
attempt to yield across metamethod/C-call boundary
You reached Twill.Admin through the root table on a client. The module waits
for Cmdr’s client half to replicate, and the lazy accessor on the root table is
not allowed to wait. Require the path directly. Once loaded, Twill.Admin works
normally.
[Twill] CmdrClient never appeared; the server must require Twill.Admin first
The client waited for Cmdr’s client half and it never arrived, because the
server never required Twill.Admin. The server require is what moves it into
ReplicatedStorage.
Every command answers Admin commands are closed
Twill.Admin.Configure has not been called. The gate refuses everything until
it is told who may do what, which is the only safe direction for that mistake.
Admin commands are not ready yet
The client has not yet received the rank settings through replication. It clears on its own.
You are not allowed to use the console or You are not allowed to run that
The first is the console floor, the second is that command’s own required rank. Both are checked again on the server whatever the client decided.
Too many commands at once. Wait a moment.
Submissions are metered per player. The log records who was turned away and how many attempts went unreported.
Admin is already configured
Configure runs once, for the same reason as the other gates.
A ban of 7d lasts seven seconds
Not from Twill’s own moderation command, which reads durations exactly. This
is Cmdr’s built-in duration type, which resolves units by fuzzy match. Check
which type your own command declares.
A big: value is whole digits, such as big:1500.
From playerdata set. The big: mark writes a
big number, so what follows it has to be digits, with an
optional leading minus. Anything else is refused rather than stored as the text
big:whatever.
You cannot grant rank N; your own is M
From rank set. The console decides who may run what by rank, so granting one
at or above your own would hand out your own authority. The most anyone can
create is somebody strictly below themselves. rank also refuses to change your
own rank and to touch anybody already at your rank or above.
No store is configured, so there is nothing to save
From saveall, in a game that never calls Data.Configure.
Not a fault; a game without saved data has nothing for this command to do.
That is not a seed a round could have revealed
From verifyroll. The seed is not thirty-two bytes of hexadecimal, so it cannot
be one Random.Commit produced. Check it was pasted
whole. A seed that is well formed but wrong reports a mismatch instead, which is
a different answer.
'X.Y' names a path. This action takes a whole key
From repl freeze, unfreeze, or throttle. Those name a whole replicated
key, and a dotted path is refused rather than acted on as if it were one. repl get reads inside a key, and takes the path.
Nothing is held at 'X' for everybody
From repl get. Either nothing has written that key yet, or it was written with
Replication.SetFor, which gives each player their own copy. Read those with
repl getfor <user> <key>.
twill net marks a remote UNSERVED
It was declared and never handed to Net.Handle. A client
firing it reaches nothing, silently. This is the diagnosis, not a fault in the
console.
A moderation command refuses with X ranks as high as you do
Deliberate. Nobody may act on themselves or on anyone standing as high as they do. The check covers targets present on this server, since somebody elsewhere has no rank to compare.
Monetization
Section titled “Monetization”no handler for product 123; leaving it unprocessed
No HandleProduct was registered for that id, so the receipt is left for Roblox
to redeliver. Register the handler and the pending purchase lands on its own.
product 123 errored for 'X': ...
Your grant handler threw. The receipt is answered as not processed, so it is retried rather than lost.
purchase 123 was not confirmed saved; Roblox will retry it
The reward was written but the save was not confirmed in time. The record of what was granted is what makes that retry safe.
product 123 already has a handler
One handler per product. A second is refused rather than replacing the first, since a silently replaced handler stops paying without saying so.
A pass bought during play does not take effect
It should, without any code from you. If it does not, the cache can be cleared
with ForgetPasses, but check first that the purchase actually completed.
could not check pass 123 for 'X': ...
The ownership check failed. It reads as not owned and is not remembered, so it is asked again rather than settled against the player.
Leaderstats
Section titled “Leaderstats”A stat never appears
The key it watches is not replicated, or the value is one no value object can hold. A value that cannot be shown leaves the stat as it was rather than clearing it.
leaderstat 'X' is already bound
Two systems bound a stat under the same name. Binding adds to the list rather than replacing it, so names have to be unique across every caller.
Leaderstats.Bind expects a list of entries: ...
The list is malformed. The reason names the field that failed.
A big number shows but never sorts
The player list sorts IntValue and NumberValue only. See
Count past the number limit for the way around
it.
Filtering
Section titled “Filtering”Filter returns nil
The filter could not be reached. That is the designed behaviour: it never
returns the text that went in. Decide what to show instead, and never write
Filter.ForBroadcast(text, id) or text.
could not check text from 123: ... or could not read filtered text from 123: ...
The platform call failed, or reading the result failed after the check
succeeded. Both answer nil.
Filtering is being rate limited
Filter once when text is submitted, store the result, and show the stored result. Filtering on every draw exhausts the per-user limit and achieves nothing.
Cross-server and configs
Section titled “Cross-server and configs”These come from Shared, Teleport,
Board, and Config.
a message on 'X' was not published: ...
Shared.Publish ran out of tries, or this server’s publishing allowance stayed
full for the whole wait. Messages are best effort, so nothing that matters may
depend on one arriving.
not listening to 'X': this server is at its subscription allowance
The server already holds as many subscriptions as its player count allows. Close subscriptions you no longer need; each one is released when its owner bag closes.
'X' in 'Y' was not written: ... from Twill.Shared
A memory store write failed after its retries. A reason naming
DataStructureMemoryOverLimit means the experience’s memory quota is full:
shorten lifetimes or remove entries you no longer need.
N player(s) could not be sent to X: ... or 'P' could not be sent to X (Flooded): ...
A teleport failed after its retries, or the platform turned a player down for a
reason waiting cannot fix. Teleport.OnFailed fires for each player, with the
Enum.TeleportResult.
'P' arrived carrying data, but Token is not configured to read it
The destination place never called Token.Configure. Every place in the
experience that receives data needs the same secret.
'X' on 'Y' was not written and waits for the next try: ...
A leaderboard write failed. The change stays queued, merged with anything asked for since, and goes again on the next flush.
configs could not be loaded (...); defaults stand in while this keeps trying
Experience configs are unreachable, usually because the place is not published or configs have never been created. Every key reads its default until they arrive.
'X' was delivered as a string but its default is a number; the default is used
A published config value has a different type from the default declared for
it. Fix the value in the Creator Hub, or the default in Config.Configure.
ConfigService: Config value not found for key "X"
Written by the engine, not by Twill, when a declared key has no published value. The default is used. Create the key in the Creator Hub to silence it.
Trade kit
Section titled “Trade kit”These come from the Trade kit.
Trade.Configure needs Data configured first
Trade.Configure ran before Data.Configure. Configure Data first, in the
same Init.
kind 'X' needs Has, Take and Give
A kind of your own is missing one of its three functions. Use a built-in kind, or supply all three.
kind 'X' has a Describe that is not a function
A kind’s Describe must be a function taking the data and the id, or be left
out.
CanTrade errored: ...
Your CanTrade rule raised. The ask is refused, and the player is told trading
is not possible right now. Fix the rule; it should return false and a reason
instead of raising.
Notice: the offer changed; look at it again
A Ready or Confirm reached the server after one of the offers changed. The
player’s view holds the changed offers, so they can ask again.
Notice: wait a moment before trading again
The player completed a trade less than Cooldown seconds ago.
trade X was made, but a save has not landed yet; it goes with the next one
The swap was made and both players’ data changed, but a save did not confirm within 20 seconds. The data is still held and saves with the next write. Nothing needs undoing.
trade X failed: ...
Something raised while a trade was being completed, outside the swap itself.
When the swap had not run yet, nothing moved, and both players are told the
trade failed. When it had, the trade is shown as completed with Saved set to
false, and the data saves with the next write. The error names what raised.
Trade.X is client only; its server half decides trades
A client call such as Trade.Request ran on the server, from a require of the
client half by path. On the server, use Twill.Kits.Trade, which is the server
half there.
Inventory and Wallet kits
Section titled “Inventory and Wallet kits”These come from the Inventory kit and the
Wallet kit. A change either kit turns down is not logged: the
call returns false and the reason, so print the second return value.
Inventory is used before Inventory.Configure
A call reached the kit before its setup ran. Call Inventory.Configure in an
Init, after Data.Configure. Wallet is used before Wallet.Configure means
the same for Wallet.
Default must name one of the containers
Containers lists more than one container and Default is missing, or names
none of them. Set Default to the container a call means when it names none.
an item needs a name of 1 to 64 characters with no dot
An item, container, or currency name is empty, too long, or holds a dot. A replicated path is separated by dots, so a name cannot hold one.
at most 5 currencies can be tracked
More than 5 currencies set Track = true. The economy dashboard takes 5.
'Bag' is full
The change would take the container past its Capacity. Capacity counts
entries: one for each counted item, whatever its count, and one for each
one-of-a-kind item.
'Sword' is removed by the id of the one to remove
Remove or Move was given the name of a one-of-a-kind item. Pass the id that
Inventory.Add returned, or one read from the container’s Items.
'Bag' is damaged
The saved field holds something other than the kit’s own shape, from a write
made outside the kit. The kit refuses to change it. Repair the field by hand,
and pass Inventory.Check to Validate so it cannot be saved that way.
a transaction for 'X' yielded, so it was undone
The function given to Data.Transact yielded, so its changes were undone. Do
the yielding work before or after the transaction.
The client halves read nothing until Inventory and Wallet are listed under
Replicate in Data.Configure.
Studio and tooling
Section titled “Studio and tooling”Edits to a module appear to have no effect
The Edit-mode VM caches modules between executions. After editing a module’s source, verify through a playtest, not through the command bar.
Studio disconnects repeatedly while testing
Test code that connects to a global service and then destroys its own folder
leaves the connection alive. :Destroy() on a parent does not disconnect a
connection to Players. Close and reopen the place to clear the Edit VM, and
put the connection in a Scope bag.
Data does not persist between playtests
Enable Studio Access to API Services under Game Settings, Security.
Without it Studio cannot reach a DataStore, so Data runs on stand-in stores
and every session starts from the template.
Discord refuses requests from Roblox game servers ...
Error.Install was given a Discord webhook
directly. Reports arrive from Studio and not from a live server. Post through a
proxy that forwards to Discord.
Purchases cannot be tested
They cannot be simulated in Studio. Publish to a private test place and buy with a real account.
When nothing here matches
Section titled “When nothing here matches”- Raise the level with
Twill.Log.SetLevel("Debug")and reproduce. - Install
Error.Installso failures nobody handled leave a record with their trace. - Read the call-site in the warning. It names the line outside Twill that caused it, which is usually the one to change.