Skip to main content

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​

  1. Readiness: socket open is not IOSignal ready. Use the CID, manual subscriptions, and sends after ready.
  2. Channel scope: room and room#topic are explicit channels; #topic uses the server's external-IP home grouping. A HOME CHANNEL is not authentication. See tags and HOME CHANNEL.
  3. Direct reception: a message sent to peerCid@rtc arrives at on('@rtc'), not message. Registering the same processing on both @ and @rtc runs it twice.
  4. Subscription order: on() does not subscribe. Repeat manual subscriptions on every ready; follow the subscription guide.
  5. Redirects: public servers may redirect before the first ready. Distinguish that from disconnection after readiness and bound the wait.
  6. Roles: room capacity, permissions, device command meanings, and WebRTC offer ownership are application rules.
  7. 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 assumptionActual behaviorVerify
import { IO } from 'iosignal' in a browserThe 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 readyCall manual subscriptions inside the ready handler. Before the server issues a CID, the session and subscription ordering are not established.Lifecycle
Assuming listen() subscribes immediatelyFor 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 messageDirect signals are not delivered to message. Use on('@', ...) or the exact @topic event.Client API
Registering subscribe('@topic') for direct receptionDirect 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 charactersThe 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 valueThe server operator sets quota. Read io.quota.maxMessageBytes after ready; do not hard-code a value.Server API
Assuming the CID survives reconnectionA 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 identityfrom 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 numberA 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 automaticallyArduino 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.