j7tracker

Errors & Limits

Every error and rate limit on the feed socket and the accounts API.

Limits

WhereLimitOver it
Feed socket5 connections per user, shared with your app tabsToo many connections
Feed socket15 client → server messages per second per socketDropped silently
Feed socketServer pings every 30 sDropped after 60 s without a pong (Socket.IO answers for you)
GET /api/watched-accounts30 per 10 s per user429 rate_limited, blocked 30 s
POST account writes20 per 10 s per user429 rate_limited, blocked 45 s
POST account writes3 running at once per user429 too_many_inflight
POST /api/accounts/available25,000 handles per call400 too_many

Every 429 carries a Retry-After header (seconds). A block lasts its full time even if you stop, so back off instead of retrying in a loop, and send account writes one after another rather than in parallel.

Feed socket

Connect errors arrive on Socket.IO's connect_error as err.message. Errors after user_connected arrive as an auth_error event.

{
    // The JWT in `auth.token` is expired or isn't an access token. Log in again; don't retry with the same token.
    INVALID_TOKEN: {
        event: 'connect_error',
        message: 'Invalid token',
    },

    // The account behind the JWT is disabled. Final.
    ACCOUNT_DISABLED: {
        event: 'connect_error',
        message: 'Account disabled',
    },

    // The JWT doesn't map to a user.
    UNKNOWN_USER: {
        event: 'connect_error',
        message: 'Unknown user',
    },

    // You already have 5 feed sockets open (app tabs count). Close one.
    TOO_MANY_CONNECTIONS: {
        event: 'connect_error' | 'auth_error',
        message: 'Too many connections',
    },

    // The JWT sent in `user_connected` failed. Log in again.
    INVALID_SESSION: {
        event: 'auth_error',
        message: 'Invalid session',
    },
}

Accounts API

Every accounts route answers errors with an HTTP status and a JSON body:

interface ErrorResponse {
    ok: false; // `success: false` on GET /api/watched-accounts
    code: string; // Short stable code, match on this
    error: string; // Human-readable message
}

Two errors come before auth and have no code: { "error": "unauthorized" } (401) and { "error": "origin not allowed" } (403).

{
    // No JWT, or an invalid one, in `Authorization: Bearer` / `x-session-id`.
    UNAUTHORIZED: {
        status: 401,
        error: 'unauthorized',
    },

    // A browser request from an origin other than j7tracker. Call the API from a server or script.
    ORIGIN_NOT_ALLOWED: {
        status: 403,
        error: 'origin not allowed',
    },

    // Your account is disabled.
    disabled: {
        status: 403,
        error: 'Account disabled',
    },

    // The JWT is valid but its user no longer exists.
    no_user: {
        status: 404,
        error: 'User not found',
    },

    // Empty handle, or no handles in a batch body.
    invalid_handle: {
        status: 400,
        error: 'Invalid account handle' | 'handle is required' | 'handles[] required',
    },

    // More than 25,000 handles in one body.
    too_many: {
        status: 400,
        error: 'too many handles',
    },

    // The handle is already in your custom or available list.
    already_added: {
        status: 409,
        error: '@<handle> is already in your custom accounts',
    },

    // Nobody tracks this handle, so it can't be added as an available account.
    not_available: {
        status: 404,
        error: '@<handle> is not in the available accounts list',
    },

    // Fewer than 15 deploys and no purchased slots.
    no_deploys: {
        status: 403,
        error: 'You need at least 15 deploys to add custom accounts. You have <n> deploys.',
    },

    // Every slot is used. Remove a custom account or buy more slots.
    limit_reached: {
        status: 403,
        error:
            | "You've reached your limit of <max> custom accounts (<n> deploys)."
            | 'You can track 1 custom account (15+ deploys). Remove @<handle> first, or reach 50 deploys for 2 accounts.',
    },

    // The X account doesn't exist or is unavailable.
    tracking_failed_invalid: {
        status: 422,
        error: 'Could not track @<handle> - account does not exist or is unavailable',
    },

    // J7's tracking capacity is full. Contact an admin.
    tracking_failed_quota: {
        status: 429,
        error: 'Could not track @<handle> - API account limit reached. Contact admin to upgrade.',
    },

    // The tracking provider failed. Retry shortly.
    tracking_failed_other: {
        status: 502,
        error: 'Could not track @<handle> - tracking provider error, try again shortly',
    },

    // The provider refused to stop tracking. Nothing was changed; retry.
    untrack_failed: {
        status: 502,
        error: 'Could not remove @<handle> - tracking provider error, nothing was changed. Try again shortly.',
    },

    // Over a rate limit. Wait `Retry-After` seconds.
    rate_limited: {
        status: 429,
        error: 'Too many requests, slow down',
    },

    // 3 account writes are already running for you. Wait for them to finish.
    too_many_inflight: {
        status: 429,
        error: 'Too many account changes in progress, wait for them to finish',
    },

    // Server error on our end. Retry shortly.
    internal_error: {
        status: 500 | 503,
        error: 'Could not save your account, try again shortly',
    },
}

On this page