Errors and limits
Every host response is either {"ok": true, "v": ...} or {"ok": false, "e": "<code>", "m": "<message>"}.
| Code | Python | Rust (ErrorKind) |
C | Meaning |
|---|---|---|---|---|
| — | — | — | FG_OK = 0 |
success |
denied |
Denied |
Denied |
FG_DENIED = 1 |
permission not granted or action forbidden |
invalid |
Invalid |
Invalid |
FG_INVALID = 2 |
bad arguments |
not_found |
NotFound |
NotFound |
FG_NOT_FOUND = 3 |
object not found |
quota |
QuotaExceeded |
Quota |
FG_QUOTA = 4 |
quota used up |
limit |
LimitExceeded |
Limit |
FG_LIMIT = 5 |
rate or size limit exceeded |
unavailable |
Unavailable |
Unavailable |
FG_UNAVAILABLE = 6 |
unavailable right now |
| anything else | Failed |
Failed |
FG_FAILED = 7 |
other failure |
| — | — | Transport |
FG_TRANSPORT = 8 |
the host call failed |
Rust also has Cancelled for cancelled calls.
Network transport failures (blocked, dns, connect, tls, timeout, closed, response, redirect) arrive as Failed with the specific name in .code; see Network operations.
All Python exceptions inherit from FreshgramError and have code and message attributes.
try: freshgram.messages.send(chat, "hi")except freshgram.Denied: freshgram.ui.toast("The messages.send permission is needed")except freshgram.LimitExceeded: pass # too oftenFixed messages
Section titled “Fixed messages”The m text of many failures is fixed, so you can recognise it. In Python it is e.message, and str(e) is "code: message".
| Operation | Message (code) |
|---|---|
| any operation | denied: a permission id such as "messages.send", or “this chat”, “this user”, “only right after a user action” |
| rate limits | limit: “messages are sent too often”, “this is done too often”, “toasts are shown too often”, “notifications are shown too often”, “pictures are processed too often”, “usernames are resolved too often” (users.resolve, channels.resolve), “members are moderated too often” (chats.ban, chats.unban), “members are listed too often” (chats.members, chats.admins), “bots are asked too often” (bots.inline_query, bots.press_button), “windows are updated too often” |
messages.react |
“the reaction was not set” |
messages.forward |
“the messages were not forwarded” |
chats.mark_read |
“the chat was not marked as read” |
chats.action |
“the action was not sent” (an unknown kind is checked by the app, not by the host) |
chats.mute, chats.archive, chats.pin |
“the chat was not changed” |
users.block, users.unblock |
“the user was not changed” |
chats.ban, chats.unban |
“the member was not changed” |
ghost.set |
“ghost mode was not changed” |
bots.send_inline_result |
“the result was not sent” |
stickers.send |
“the sticker was not sent” |
notify.show |
“the notification was not shown” |
clipboard.write |
“the clipboard was not changed” |
composer.insert |
“the text was not inserted” |
fs.list, fs.stat, fs.read, fs.write, fs.mkdir / fs.remove, fs.rename |
“the folder was not listed”, “no such file”, “the file was not read”, “the file was not written”, “the change was not made”, “the file was not renamed” |
files.pick, files.save |
invalid “title or filter” / “name or data”; “the file was not read” / “the file was not saved” |
storage.get, storage.set, storage.delete |
invalid “key” (empty, over 128 bytes, a control byte or not text) |
net.ws.connect |
invalid “url” (missing, not text or over 2048 bytes) |
net.socket.*, net.ws.* |
not_found “socket” for an unknown or closed socket id |
ui.toast |
invalid “undo needs an action” for undo=True without an action |
unavailable |
“awaitable calls”, “toast actions”, “windows”, “timers”, “network” and similar: the app lacks that service |
For the operations from messages.react to fs.rename the code is the one the app reports (usually failed); only the message is fixed by the host.
Silent defaults
Section titled “Silent defaults”Some wrong arguments do not raise Invalid. An integer argument that has another type is treated as absent and takes its default:
limitofstorage.keys(100);maxofnet.socket.recv(65507) andtimeoutofnet.fetch, sockets and WebSockets (10000 for connecting and sending, 1000 for receiving);net.fetchmethodthat is not text or is longer than 8 bytes becomesGET(other text, such as"get", isInvalid).
Out-of-range numbers are clamped instead of rejected (for example a timeout over 30000 ms for a socket). The exact rules are in each operation’s page.
Typical limits
Section titled “Typical limits”Exact values depend on the operation and are described with it. For example: messages with media up to 100 MiB, images up to 16 MiB and 8192 pixels per side, at most 32 pending async calls, at most 32 timers, a notification no more than once in 5 seconds, users.resolve once per second.
