Errors

Every error the SDK throws, by class and code: when it happens, what it means, and what to do. Includes the codes the UNET API passes through.

Every error the SDK throws extends UnetIdError, which has a code string. Branch on the class for the common cases, and on code for the rest. For patterns and examples, see Error handling.

import { AccessDenied, ApiError, InsufficientScope, NetworkError, RateLimited, SessionExpired, UnetIdError } from "@unet/id-web";

try {
  await unet.api.feed();
} catch (e) {
  if (e instanceof SessionExpired) {
    // sign in again
  } else if (e instanceof InsufficientScope) {
    console.log("missing permission", e.scope);
  } else if (e instanceof RateLimited) {
    console.log("retry in", e.retryAfterSeconds, "seconds");
  } else if (e instanceof ApiError) {
    console.log(e.status, e.code);
  } else if (e instanceof NetworkError || e instanceof AccessDenied || e instanceof UnetIdError) {
    console.log(e.code);
  }
}

Classes

ClasscodeWhenWhat to do
AccessDeniedaccess_deniedThe person pressed Deny on unet.social. Thrown by handleRedirectCallback().Return to your page and offer to try again. It is not an error of yours.
StateMismatchstate_mismatchThe return URL has no matching pending sign-in: the state differs, there is none, or it is older than 15 minutes.Start the sign-in again. See the FAQ.
SessionExpiredsession_expiredThere is no session, the refresh was refused because the permission is gone, there is no refresh token and the access token ended, or the API answered 401.Sign the person in again. The SDK has already cleared the session.
InsufficientScopeinsufficient_scopeThe API answered 403 with insufficient_scope. It has a scope field naming the permission. Also thrown by a realtime stream.Register the permission for your app, then sign in again with prompt: "consent". See Permissions.
RateLimitedrate_limitedThe API answered 429. It has retryAfterSeconds (or null).Wait, then retry. Or set retries so the SDK does it. See Limits.
NetworkErrornetwork_errorNo response arrived (offline, blocked, refused), a JSON request exceeded timeoutMs, or discovery or the signing keys could not be loaded.Retry later. The session is kept.
ApiErrorSee belowThe API answered with an error that is not one of the above, or the SDK refused a call before sending it. It has status (HTTP).Read code. 4xx is usually your request; 5xx is the server.
UnetIdErrorSee belowAnything else from sign-in, configuration or the server-side checks.Read code.

UnetIdError codes

These come from sign-in, configuration and the verifyAccessToken and verifyIdToken checks. The class is the plain UnetIdError.

codeThrown byMeaningWhat to do
configConstructor, verifyAccessToken, verifyIdTokenA required option is missing (clientId, redirectUri, clientSecret), the issuer is not https (http is allowed only on localhost), or Web Crypto is missing for verifyIdToken.Fix the option. The message says which.
discovery_invalidsignIn, restore, getAccessToken and anything that needs discoveryThe discovery document names another issuer than the one you configured, or an endpoint is missing, is not https, or is on another origin.Check issuer. If it is right, the server is misconfigured: its issuer must be its public https address.
issuer_mismatchhandleRedirectCallback, verifyIdTokenThe callback iss is not the configured issuer, or a discovery document names a different issuer than the one asked for.Check issuer. If it keeps happening, treat it as a possible attack.
invalid_clientToken requests, verifyAccessTokenUNET does not accept this App ID (wrong, turned off, on the other server), or, for verifyAccessToken, the App ID or Secret is wrong or the app has no secret.Check the App ID, that the app is active, and that issuer points at the right server.
invalid_responsehandleRedirectCallbackThe return URL has state but no code.Start the sign-in again.
token_errorToken requestsThe token endpoint answered with an error and no more specific code.Read the message.
userinfo_errorhandleRedirectCallback, restore, refreshUser, verifyAccessTokenThe profile could not be loaded (the status is in the message).Retry later.
introspection_errorverifyAccessTokenUNET could not check the token (the status is in the message).Treat the token as unverified. Retry later.
jwks_errorverifyIdTokenThe signing keys could not be loaded.Retry later.

The code can also be whatever the server named in an OpenID Connect error: the SDK passes it through. The ones you may meet:

codeWhenWhat to do
invalid_scopeThe authorization asks for a permission the app did not register (a new app is held to what it registered). It arrives on the return URL.Register the permission in the console, or stop asking for it.
invalid_grantA token request used a code that was already used or expired, or a refresh token that is gone. For a refresh, the SDK turns it into SessionExpired.Start the sign-in again.
invalid_request, server_error, temporarily_unavailable, login_required, consent_required, interaction_requiredStandard OpenID Connect errors, from the return URL or the token endpoint. login_required, consent_required and interaction_required only appear when you pass prompt: "none".Read the message. prompt: "none" never shows a screen, so fall back to a normal sign-in.

ApiError codes

An ApiError has status and code. Some codes are made by the SDK; the rest come from the API.

Made by the SDK

codestatusWhen
invalid_id400An id that goes into a request path is not a plain id (letters, digits, - and _ only), or the path has a . or .. segment. No request is sent.
not_media_url400api.media() was given an address that is not a UNET media address, or whose path has anything but plain file-name segments. No request is sent.
invalid_responseThe statusA success answer that is not JSON.
forbidden403A 403 without the API's insufficient_scope: usually a proxy or firewall in between.
api_errorThe statusAn error answer with no code in it.
stream_unavailableThe statusA realtime stream could not be opened.
stream_garbled502A realtime stream sent a great deal of data without a break.

Sent by the API

These are the codes the UNET API returns and the SDK passes on in code. Not every one applies to every call.

codestatusMeaning
not_found404It does not exist, or you may not see it. The API never says which.
not_allowed403A rule forbids it: blocked, private connections, comments off on that post, your own post, and the like. This is not a missing permission.
connections_private403The person hides their followers and following.
comments_disabled403Comments are off on that post.
not_following403The action needs you to follow them first, such as the profile bell.
edit_window_closed403A comment can be edited for 30 minutes after it is posted.
fediverse_off, not_available, disclosure_required403, 403, 400The Fediverse is off for the account, is not available to it, or needs the plaintext disclosure accepted when turning it on.
already_exists409The thing is already there.
pin_limit_reached409The pinned-post limit is reached. The answer also carries limit.
playlist_full409The profile music playlist is full.
content_required, content_too_long, description_too_long, nothing_to_update400The body is empty, too long (comments: 2000 characters), or has nothing to change.
invalid_request, invalid_field, invalid_query, invalid_cursor, invalid_id, invalid_username, invalid_feed_type, invalid_date, invalid_scheduled_at, invalid_coordinates, invalid_place, invalid_tag, invalid_topics, invalid_language, invalid_link, invalid_links, invalid_image_keys, invalid_gif_url, invalid_sticker_id, invalid_parent_id, invalid_reason, invalid_target_id, invalid_target_type, invalid_uri, invalid_file400A parameter or the body is not valid. The message says which.
no_long_form404The post has no long-form text.
parent_not_found404The comment you reply to is not on that post.
not_found_or_published404There is no such scheduled post, or it is already published.
payload_too_large413A picture is larger than 10 MB.
gif_provider_error502, or the provider's own 4xxThe GIF provider failed. Try again.
web_access_denied403The web version is not open to that account yet (only for UNET's own web app).
open_api_unavailable, unet_id_starting503The API is restarting. Retry in a few seconds.
internal_error500A server error. Retry later.

A 401 from the API is always SessionExpired in the SDK, whatever the body says.