Permissions#
Why a verb answers nil, "permission", and what to do about it.
Use it to
- understand why a call answered
nil, "permission" - know what a script may do in a world you do not own
- see who owns what a script makes
There are three separate gates, and they answer different questions. Almost every permission problem is a matter of working out which one you hit.
| Gate | Question |
|---|---|
| The world | what did this world's owner allow the script's owner to do here? |
| The object | does this script own what it is acting on? |
| The author | did the script's owner write it, or get it from somebody else? |
One rule sits above all three: your own script on your own body is free. A worn item and a personal HUD run as the person wearing them, so they act on that person in any world, with no grant from anybody.
1. The world#
A script acts with the authority of whoever owns it, and nothing else. The kind of world does not matter and neither does where the script happens to be standing.
- The world's owner holds every permission. Their scripts may do anything on this page.
- Anybody else holds exactly what the owner granted them, by name, on the Permissions page of the world's settings. A visitor nobody granted anything to has scripts that can act on their own objects and nothing more.
| Verb | Permission its owner needs |
|---|---|
world:spawn, world:despawn, world:move, world:tween, world.npc:spawn | Create ephemerals |
world:play_sound | Create ephemerals |
world:set_weather | Weather and ambience |
world.sky and world.sea: every verb that changes them | Weather and ambience |
world.sky:get, world.sea:get | none, because what the sky looks like is not a secret |
world.loading:set / clear | Weather and ambience |
world.loading:get | none, because the front door is not a secret |
world.terrain:* | Terraform |
world.blocks:set / fill | Dig and build with blocks |
world.build: every verb that changes pieces | Raise and take down building pieces |
world.store:set / update | the world's data permission |
world.store:get | none, because reading is public |
players.store:* | the world's data permission, including reading |
http:send | the net permission |
players:teleport, players:play_animation, players:dress, self:hold on somebody else | Act on other people's avatars |
self:sit | none for a player who clicked this object; Act on other people's avatars for anybody else |
Tip
If a verb works in your test world and refuses in somebody else's, this is almost always why. Nothing about the script changed. In your own world you are the owner and hold everything; in theirs you hold what they gave you.
The one a worn item can never hold#
http:send is the exception to everything on this page, and it is worth knowing why before you spend an afternoon on it.
Everywhere else, your own script on your own body is free: a worn attachment and a personal HUD run as you, so they act on you in any world, with no grant from anybody. That is what makes personal items work.
The network is not your body. It is the address of whoever is hosting the region you happen to be standing in. Their machine, their bandwidth, their name on the request. So http asks about the region, always, and:
- a personal HUD cannot call it, in any world, including your own;
- a worn attachment cannot call it, even the one you built;
- an object script can, if the world's owner granted
netto whoever owns it, and a world owner's own scripts hold it without asking.
2. The object#
A script acts freely on its own object: moving it, painting it, storing things in it.
Acting on another object through objects requires that you own that object too, or that you have been granted edit rights over it. Otherwise: nil, "permission".
Carrying is different: it needs an interaction#
self:hold and world:spawn{ hold = } put something in somebody else's hand, so they need Act on other people's avatars like every verb in that family, and they ask one more thing: that player must have interacted with this object.
What counts as an interaction:
- they clicked it (
on_touch) - they pressed a button on a HUD this object showed them
What does not count: standing near it, looking at it, being in the region.
-- works: the click IS the interactionself:on_touch(function(p) self:hold({ player = p.id })end) -- refused: nobody interacted with anythingplayers:on_enter(function(p) self:hold({ player = p.id }) -- nil, "permission"end)This is why a shop leaves a purchase on the ground unless the buyer pressed a button on the shop's own menu, and why handing something over from a menu works, because pressing that button was the interaction.
An object that world:spawn has just created has no history at all, which is exactly why handing a brand-new copy straight into a hand is allowed: nobody can have touched what did not exist a moment ago.
3. The author#
Everything above asks about the script's owner. That is the right question for a script its owner wrote. It is the wrong one for a script its owner bought or was given, because it would hand a stranger's code the whole authority of whoever installed it.
So a script you did not write runs in a box: full authority over its own object and that object's group, and read-only outside it. It still acts freely on the person wearing it, which is the rule at the top of this page.
The world's owner can hand part of that back, one product at a time. Some things no switch reaches, however much the owner trusts the product:
| A script you did not write can never | Why |
|---|---|
| sculpt terrain, place blocks, raise building pieces | they reshape the place for everybody |
| teleport, or take the camera or input of, somebody else | those are somebody's body and eyes |
local ok, why = players:teleport(p.id, spawn_point)if not ok then print("could not respawn: " .. why) -- "permission"endCareful
Check what these answer. A script that assumes it holds everything is a script that silently breaks in the one world where it does not, and the symptom is not a crash, it is a respawn that never happens.
Visitors are not asked anything at the door. Entering a world is agreeing to that world, and who may act on other people in it is the owner's to decide, through Act on other people's avatars.
Latches are released for you#
set_camera, set_weapon and show_cursor are latches: they stay until something takes them off.
If the script that set one dies, because the item came off, the object was deleted or the script was re-saved, the engine hands the player back their own camera, their own aim and their own pointer. Otherwise somebody would be stuck inside their own head with nothing left in the world able to let them out.
You still want the matching call on the way out (clear_weapon on on_drop, hide_cursor when the menu closes). The release is a safety net, not the design.
Ownership of things a script makes#
An object created by world:spawn belongs to the owner of the script that made it, not to whoever triggered it. A copy made from a prototype carries its scripts across with the builder as their creator.
See also#
- Limits and refusals has every reason, in one table
Updated 17 October 2026