Testing and debugging
Fix creation errors, understand caching, and avoid script injection.
Debugging loop
1
Preview with sample input
2
Check what is actually stored
3
Check who can reach it
4
Fix and re-save
;cc set on an existing name overwrites it and keeps a revision, so you can iterate freely.Creation errors
missing separator
missing separator
Add a standalone
--, =>, or -> between the definition and the response. It must have whitespace around it.already a command name
already a command name
The name collides with a built-in raze command or with the reserved names
cc, customcommand, customcommands. Pick another.invalid name
invalid name
Names allow only lowercase letters, digits,
_, and -, up to 32 characters.invalid argument declaration
invalid argument declaration
Use
(name), [name], (name...), or [name...]. Mismatched brackets such as <member] are rejected, and names must start with a letter.cannot follow a rest argument
cannot follow a rest argument
A rest argument swallows the remainder of the input, so it has to be the last declaration.
needs a permission which you don't have
needs a permission which you don't have
The script contains an action and you don’t hold the Discord permission it maps to. You cannot create a command that does more than you can.
tier limit reached
tier limit reached
You’ve hit your tier’s cap on saved commands. Delete one, or upgrade with
;upgrade.Runtime behaviour to expect
Caching
Custom commands are cached in memory for 30 seconds per server.- Editing through
;cc—set,remove,enable,disable,allow,unallow,deny,undeny,requireperm, andrestrictions clearall clear the cache immediately, so your change is live at once. - Editing the database directly — wait up to 30 seconds, or restart the bot.
User input is inert
Everything a member types is neutralised before it reaches the script: braces in argument values are converted to lookalike characters that no tag pattern matches. The same applies to any placeholder whose value is user-controlled text — usernames, nicknames, role names, channel names and topics.Shout: ❴db.set:secrets:key:value❵Nothing is written, no action fires, and no output directive is smuggled in. The text is echoed with the braces visibly replaced.
Output directives are read from the saved script before substitution, so
{delete} or {silent} typed by an invoker can never take effect either.Still worth doing
Restrict the powerful ones
A command that bans or writes to the database should still be limited to trusted roles with an allow list.
Watch the allow-list bypass
A user or role allow entry skips the action permission check. Add someone deliberately, not for convenience.
Mind self-assign roles
A top-level
{add_role:} applies to whoever runs the command. Only put roles there that anyone reaching the command should be able to hold.Preview first
;cc preview renders the whole script without performing any action, write, or delivery side effect.
