FAQ: common mistakes
Use this list when writing code yourself and when reviewing AI-generated code. For symptom-based diagnosis, see troubleshooting.
Behaviors to verify
- Readiness: socket open is not IOSignal
ready. Use the CID, manual subscriptions, and sends afterready. - Channel scope:
roomandroom#topicare explicit channels;#topicuses the server's external-IP home grouping. A HOME CHANNEL is not authentication. See tags and HOME CHANNEL. - Direct reception: a message sent to
peerCid@rtcarrives aton('@rtc'), notmessage. Registering the same processing on both@and@rtcruns it twice. - Subscription order:
on()does not subscribe. Repeat manual subscriptions on everyready; follow the subscription guide. - Redirects: public servers may redirect before the first
ready. Distinguish that from disconnection after readiness and bound the wait. - Roles: room capacity, permissions, device command meanings, and WebRTC offer ownership are application rules.
- Success:
signal()does not confirm that the peer finished its work. Design replies and verify actual results when needed.
Check payload for data types, the client API for tag length, and the server API for quota. If the docs and your installed version differ, check that version's types and source.
Common misconceptions
| Common assumption | Actual behavior | Verify |
|---|---|---|
import { IO } from 'iosignal' in a browser | The root iosignal entry is for Node.js. Browser bundlers use import IO from 'iosignal/io'; CDN pages use the IIFE/ESM browser build. | Client API |
Calling subscribe() before ready | Call manual subscriptions inside the ready handler. Before the server issues a CID, the session and subscription ordering are not established. | Lifecycle |
Assuming listen() subscribes immediately | For a normal tag, listen() only registers the handler and tag. The subscription packet is sent when the client receives its CID and becomes ready. | Lifecycle |
Receiving direct signals through message | Direct signals are not delivered to message. Use on('@', ...) or the exact @topic event. | Client API |
Registering subscribe('@topic') for direct reception | Direct tags are not server subscriptions. subscribe('@topic') and unsubscribe('@topic') throw TypeError and are not sent. Register with on() or listen(). | Lifecycle |
| Measuring tag length in characters | The tag limit is 255 UTF-8 bytes. For example, 85 Korean characters are 255 bytes and 86 exceed it. | Client API |
| Treating quota as a fixed, deployment-wide value | The server operator sets quota. Read io.quota.maxMessageBytes after ready; do not hard-code a value. | Server API |
| Assuming the CID survives reconnection | A closed connection invalidates its CID, and the next connection may receive a different one. Re-read io.cid on every ready and re-register manual subscribe() calls. | Authentication |
Trusting payload from as an authenticated identity | from is an application field, not a sender ID verified by IOSignal. Use server authentication results or application checks for authorization. | Server authentication |
Expecting signal('room', 42) to arrive as a number | A single number is encoded as TEXT and arrives as the string '42'. Use an object or multiple arguments to preserve a number. | Data format |
| Assuming Arduino restores JS objects automatically | Arduino callbacks receive the type, raw bytes, and length. Parse OBJECT/MJSON/MBA in the application to recover objects or multiple arguments. | Data format |
Quota and limits
Quota is a policy set by the server operator, not a library constant (quotas profiles, anonymousQuota, and each account's role and quota). Public services follow the provider's policy. Keep protocol limits such as the 255-byte tag separate from quota.