Build panels
Error codes and limits
The ten codes a bridge call can fail with, what triggers each one and what to do about it, and every limit a panel lives under.
Reading an error
Every SDK call returns a promise. When Deska refuses, the promise rejects with an Error whose code is one of the ten below; the same text is its message. Codes are stable: match on them, never on wording.
async function call(run) {
try {
return { ok: true, value: await run() }
} catch (err) {
return { ok: false, code: err.code ?? 'host_error' }
}
}
const saved = await call(() => deska.storage.set('notes', notes))
if (!saved.ok && saved.code === 'storage_full') banner('Storage is full. Delete a note to make room.')
if (!saved.ok && saved.code === 'rate_limited') setTimeout(save, 1000)SDK Playground triggers most of these on purpose and shows the line of code each one ran.
The ten codes
| Code | What triggers it | What to do |
|---|---|---|
not_ready | A call reached Deska before the page finished its handshake. The SDK queues calls until ready() resolves, so through the SDK you will not see it. | Await deska.ready() if you talk to the bridge by hand. |
unknown_method | A method Deska does not know, or a name longer than 32 characters. Only possible when posting messages by hand. | Use the SDK’s methods; check sdk in panel.json. |
permission_denied | The method needs a permission panel.json does not ask for, or the person did not allow at install. extras.set without contributes.extras too. | Add the permission to panel.json, or check init.permissions and hide the feature when it is missing. |
invalid_args | An argument broke a rule: a null, empty or long title, a storage key over 256 characters, an http link, an unknown Extras field, a value with no JSON form, a file that is not a Blob, or an image to copy that is not a PNG or JPEG or does not decode. | Fix the call. Each method’s rules are on the SDK reference. |
rate_limited | More than 20 calls a second (bursts of 40), a second notice within ten seconds, or a second link within a second. | Batch work, send only what changed, and retry later for notices. |
too_large | The call’s arguments are over 64 KB or nest deeper than 32 levels, a clipboard text is over 64 KB, or a file or image is over 32 MB. | Split the data across several keys, send less, or make the file smaller. |
storage_full | A storage write would take the package past 256 KB, or every community panel on the computer past 2 MB together. A file would take the package past 256 MB or 2,000 files, or every package past 1 GB together. | Tell the person, keep their edit on screen, and compact or remove old data or files. |
not_focused | openUrl, clipboard.write, clipboard.writeImage or files.save while the panel does not have focus: from a timer, after a long wait, or after the person moved to another panel. | Call it from the click or key press itself, before any slow await. |
declined | For openUrl: the person pressed Cancel, another of Deska’s questions was open, or this page was refused once already. For files.save: a save from this panel, or another of Deska’s questions, was already open. | Take it quietly. Do not ask again in a loop; Deska will not show the link question again until the page reloads. |
host_error | Deska failed to do what was asked, like the system clipboard refusing a write or a saved file that could not be written. | Say it did not work and let the person try again. |
Limits on every frame
| Limit | Value | Past it |
|---|---|---|
| Calls | 20 a second on average, bursts of 40 | rate_limited |
| Messages | More than 400 in one second | Deska takes the frame down |
| Arguments | 64 KB once serialized, nested at most 32 deep | too_large |
| A file in a call | The Blob given to files.put, files.save or clipboard.writeImage: 32 MB | too_large |
| Method name | 32 characters | unknown_method |
| Call id | 64 characters | Dropped unanswered |
Arguments are measured before Deska reads them, so a huge or sparse array costs the page nothing to send and Deska nothing to refuse. The limits count per frame: two copies of a panel each get their own.
// One write instead of one per item
await deska.storage.set('habits', { version: 2, habits, days })
// One notice for several changes
await deska.notify({ title: `${changed.length} services changed`, body: changed.join(', ') })Limits by method
| Method | Limit |
|---|---|
storage.get, set, remove | Keys of 1 to 256 characters |
storage.set | 256 KB per package, 2 MB for all packages on the computer |
setTitle | 1 to 60 characters, never cut; written at most four times a second |
notify | Title up to 80, body up to 240 characters; one every 10 seconds |
openUrl | https only, up to 2048 characters, with focus; one a second; asks per host |
clipboard.write | Up to 64 KB, with focus |
clipboard.writeImage | A PNG or JPEG up to 32 MB, with focus |
files.put | 32 MB per file; 256 MB and 2,000 files per package; 1 GB for all packages on the computer |
files.save | Up to 32 MB, a name up to 120 characters, with focus; one save at a time |
extras.set | State up to 60 characters; progress 0 to 1; only the four fields |
When the panel itself stops
Some failures are not a code but a state the panel shows instead of your page:
| The panel says | Why | What brings it back |
|---|---|---|
| Disconnected, and that it opened another page | The page left its address: a link followed in the frame, a form that navigated, or a change to location. | Reload. Open links with deska.openUrl and handle form submit in script. |
| Disconnected, and that Deska stopped it | More than 400 messages in one second. | Reload, after finding the loop that floods. |
| Does not pass the checks | A loaded folder stopped passing the package checks after an edit. | Fix what the list says; Deska loads it again on save. |
| Not installed | The package is not on this computer. | Install it from the Panel Library. |
| Removed by Deska | Deska withdrew the panel or this version. | Nothing; it no longer loads. |
Errors when publishing
Publishing has its own refusals (a version that exists, an id another account owns, a package over 5 MB, too many publishes). They are listed with what to do on Publishing.