Skip to content

Handling errors ​

Which calls throw, and which don't ​

Most calls throw when something goes wrong. A few return a value instead, because failure is a normal outcome for them:

CallOn failure
Lookups, request(), resource(), collection readsThrow
account.gifts.send()Returns { ok: false, error }
account.friends.add() / .remove()Returns false
account.wishlist.add() / .remove()Returns false
account.followers.follow() / .unfollow()Returns false when the API refuses; other errors throw
relation() methods such as user.profile(), product.parent()Return null when the relation doesn't exist

API errors: IMVUAPIError ​

When IMVU answers with a failure, @imvu/rest throws IMVUAPIError. Its apiCode is IMVU's machine-readable error code, and message is the human-readable text:

ts
import { IMVUAPIError } from '@imvu/rest';

try {
  await client.request(`/user/user-${client.account.id}/friends/user-${id}`, { method: 'DELETE' });
} catch (error) {
  if (error instanceof IMVUAPIError) {
    console.error(`IMVU refused (${error.apiCode}): ${error.message}`);
    console.error(error.response); // the full failure envelope
  } else {
    throw error; // network failure, a non-JSON response, …
  }
}

Other errors you may see from the REST layer:

  • A network error from fetch itself (DNS, TLS, offline). Pass a signal in the request options to add timeouts or cancellation.
  • Expected a JSON response …: IMVU answered with something other than JSON, usually an HTML error page during an outage or when blocked.
  • You must be logged into to access account information!: you read client.account before login() finished.

Error codes worth knowing ​

apiCodeMeaning
VERIFY-001The session must solve a proof-of-work challenge first. Handled for you; see below.
RATE-001Too many messages too fast. Also returned with "verify email" when an unverified account messages non-friends.
CHAT_PARTICIPANT-001/-002The room is full. Room lists lag, so this happens even when it looked open.
CHAT_PARTICIPANT-004The room is unavailable.

Proof of work ​

When IMVU decides a session is busy, it rejects requests with VERIFY-001 until the session solves a proof-of-work challenge: a time-lock puzzle that costs CPU time and can't be parallelized. @imvu/client handles this for you, the way the web client does:

  1. it lists the session's outstanding challenges (GET /pow);
  2. it solves each one;
  3. it posts the solutions back;
  4. it retries the original request, up to maxPowRetries (3) times.

You'll only see VERIFY-001 if solving keeps failing. With @imvu/rest alone, pass a solver to turn the same behaviour on:

ts
import { REST } from '@imvu/rest';
import { solveRswAsync } from '@imvu/xmlrpc';

const rest = new REST({ proofOfWork: (nonce) => solveRswAsync(nonce) });
await rest.solveChallenges(); // or solve on demand; resolves to how many were handled

The XML-RPC gateway's equivalent, fault 110, is routed to the same challenges by client.xmlrpc.

Gift results ​

Sending a gift spends credits, so it never throws for an expected failure. It distinguishes rejected (IMVU said no; nothing happened) from indeterminate (the request may or may not have gone through):

ts
const result = await client.account.gifts.send({ recipient, product });

if (!result.ok) {
  const { error } = result;
  if (error.kind === 'rejected') {
    // error.reason: 'insufficient_credits' | 'already_owned' | 'not_giftable'
    //               | 'recipient_restricted' | 'unknown'
  } else {
    // 'indeterminate': check before retrying, or you may gift twice.
  }
}

See Gifting for a complete flow.

Other packages ​

PackageErrorWhen
@imvu/clientCollectionNotWatchableErrorwatch() on a collection that publishes no updates.
@imvu/clientRangeErrorpage() with a negative offset or a non-positive limit.
@imvu/clientErrorsession.send() on a closed ChatSession, or IMQ rejecting a chat line.
@imvu/verifyRangeErrorA challenge secret shorter than 16 bytes.
@imvu/xmlrpcXmlRpcFaultThe gateway returned a fault. Compare code with FaultCode.
@imvu/xmlrpcXmlRpcHttpErrorThe gateway answered with a non-200 HTTP status.
@imvu/chknChknErrorA malformed CFL/CHKN archive, LZMA stream or product template.
@imvu/cal3dCal3DErrorThe bytes aren't a Cal3D file, or are corrupt.

Common XML-RPC fault codes:

ts
import { FaultCode, XmlRpcFault } from '@imvu/xmlrpc';

if (error instanceof XmlRpcFault) {
  switch (error.code) {
    case FaultCode.InvalidLoginOrPassword: // 11
    case FaultCode.TwoFactorRequired: // 107
    case FaultCode.InvalidAuthData: // 30: session replaced by another login
    case FaultCode.ProofOfWorkRequired: // 110: solved and retried by client.xmlrpc
  }
}

client.xmlrpc already recovers from InvalidAuthData by logging in once more, so you'll only see it when using XmlRpcGateway directly.

Released under the MIT License.