Tinylib
DiscoverDocsSign in
Sign in
Tinylib
AboutDiscoverDocsMake an appPricingTermsPrivacyDeveloper TermsContact

Start

  • Quickstart
  • How Tinylib works

Guides

  • Data
  • Rooms and rules
  • Games
  • Friends
  • Places and links
  • Reminders and notifications
  • Publishing
  • Errors and offline
    • Handle a failed call
    • Handle a dismissed sheet
    • Without a connection
    • When a request loses its connection
    • Errors in the rules
    • Find errors from live rooms
  • Platforms

Client API

  • tinylib
  • tinylib.data
  • tinylib.rooms
  • tinylib.invitations
  • tinylib.friends
  • tinylib.places
  • tinylib.reminders
  • Types
  • tinylib-sdk/kits

Rules API

  • Kinds
  • ctx

Reference

  • tinylib.json
  • Command line
  • Limits

Plain text

  • llms.txt
  • llms-full.txt

Errors and offline

Handle a failed call

A call fails with a TinylibError, an Error with a code that says what happened and a message you can show the user. A refusal from your rules carries your own sentence.

This form joins a room by its short code, and shows a code that matches no room as the field's own error:

HTML
<form id="join"><input name="code" required> <button>Join</button></form>
JavaScript
const form = document.querySelector('#join') const codeField = form.elements.code codeField.oninput = () => codeField.setCustomValidity('') form.onsubmit = async (event) => { event.preventDefault() try { const { id } = await tinylib.rooms.join(codeField.value) tinylib.places.go(`game/${id}`) } catch (error) { if (error.code === 'not_found') { codeField.setCustomValidity(error.message) codeField.reportValidity() } else if (error.code) { toast(error.message) } else { throw error } } }
CodeWhat happenedWhat to do
refused
What happened
Tinylib or your rules said no, and message says why: the rules called ctx.refuse, the call needs a Tinylib account and the user has none, your app's uses lacks what the call needs, or one person has blocked the other.
What to do
Show message.
failed
What happened
Something went wrong that the user didn't cause. Your rules threw or have no handler for the input, or Tinylib's servers or the device failed.
What to do
Show message. When your rules caused it, your developer page shows the error; otherwise, trying again later may work.
offline
What happened
The call needs Tinylib's servers, and the device has no connection.
What to do
Wait for tinylib.connection.onChange, then let the user try again. A request already on its way may have arrived.
limit
What happened
The call would pass one of the limits.
What to do
Show message. A rate allows more later, and a size or a count allows more once something is removed.
not_member
What happened
The user isn't a member of the room, or no room has that id. Tinylib doesn't say which.
What to do
Take the user out of the room's screen.
ended
What happened
The room has ended, or the user deleted their data in your app.
What to do
Take the user out of the room's screen.
not_found
What happened
No short code, link, invitation, or person matches what the call was given.
What to do
Ask the user to check the code or link they used.

Each call's reference lists the codes it can fail with, and any call that reaches Tinylib's servers can also fail with failed.

A call given arguments it can't take, such as tinylib.places.go('/game'), throws a TypeError, or rejects with one if it's asynchronous. Its message is for you, not the user.

Handle a dismissed sheet

Closing one of Tinylib's sheets without choosing isn't an error. block and report resolve false, user.manageSettings resolves with the settings unchanged, and the other calls that open a sheet resolve when it closes:

JavaScript
const blocked = await tinylib.block(member.id) if (blocked) tinylib.places.go('')

Without a connection

While a room your app has open can't reach Tinylib, Tinylib shows so over your app, so your app doesn't show its own.

tinylib.connection.online says whether Tinylib's servers can be reached, and onChange calls your function when that changes:

JavaScript
const newGame = document.querySelector('#new-game') tinylib.connection.onChange(() => { newGame.disabled = !tinylib.connection.online })

A call that needs a connection rejects with offline at once when there's none. The others work with what the device keeps:

CallWithout a connection
tinylib.data
Without a connection
Reads and writes the device's copy
tinylib.reminders.set, list, and cancel
Without a connection
Work on the device's copy
tinylib.user, tinylib.places, and tinylib.now()
Without a connection
Work
rooms.open
Without a connection
Opens from the device's copy in an offline kind, and otherwise opens once the device is back online
room.act
Without a connection
Works in an offline kind, and rejects with offline otherwise
room.relay
Without a connection
Sends nothing, without an error
room.close
Without a connection
Works
rooms.list
Without a connection
Resolves with the ended and left rooms the device last heard of
rooms.data
Without a connection
Reads an ended or left room's data the device has read before, and rejects with offline otherwise
rooms.create, join, invite, getLink, and leave
Without a connection
Reject with offline
tinylib.friends
Without a connection
Every call rejects with offline
Listing, accepting, and dismissing invitations
Without a connection
Reject with offline
user.manageSettings, block, and report
Without a connection
Reject with offline

Writes and reminders made offline are sent when the connection returns. tinylib.data.onChange reports a write that fails once it arrives.

Your app opens offline once it has opened online on that device, except that Safari may delete its copy (Platforms).

When the connection drops, an open room disconnects, and Tinylib reopens it with the current view when the connection returns. Meanwhile, room.act rejects with offline outside an offline kind, and events the rules emit and other members' relays are missed.

When a request loses its connection

A request that loses its connection after it left the device rejects with offline, and Tinylib can't tell whether it arrived. A room.act may have run, and once the room reopens, its view shows whether it did. A rooms.create may have made a room, so check tinylib.rooms.list() before creating another.

An offline kind doesn't have this problem: the device sends each action until the room has it, and the room runs each one once.

Errors in the rules

When the rules throw, or an input runs past 50 milliseconds of CPU time, the input changes nothing and sends nothing. If it was a member's rooms.create or room.act, the call rejects with failed. An error never ends a room.

A join or a leave still happens when its handler throws, and only the rules' changes from it are dropped. The member is then in the room but not in the state, so keep join and leave from throwing, and write your other handlers to cope with a member the state doesn't know.

When something a handler asks for can't be done, such as a notification whose text is past 300 characters, Tinylib skips it and keeps the rest of the input. The error shows on your developer page.

Find errors from live rooms

In npx tinylib-sdk dev, the inspector shows everything your rooms do as it happens, and console.log in your rules prints to the browser's console. In live rooms, console.log goes nowhere.

Errors from live rooms show on your app's developer page, each with its kind, its input, the version, how many times it happened, and the line in your files where it happened. Tinylib never shows you a room's state or an input's data, and the Developer Terms forbid putting people's data in error messages.

PreviousPublishingNextPlatforms

On this page

  • Handle a failed call
  • Handle a dismissed sheet
  • Without a connection
  • When a request loses its connection
  • Errors in the rules
  • Find errors from live rooms