Wialon API Errors: Codes 1, 4, 6, 7 and 1004

Reference · last checked

The full Wialon Remote API error table, the 1003 reason variants, the quotas that produce each code, and how to classify them for retry logic.

A Wialon Remote API call answers with a JSON object containing an error code and nothing else that explains it. The codes are documented and there are few of them, but they split into classes that need completely different handling, and an integration that treats them uniformly produces retry storms, temporary IP blocks and silent gaps in its own history table. This page covers the full code table, the reason strings some codes carry, the published quotas that generate the rest, and a classification you can build retry logic on.

Read the reason string, not only the code

The server returns errors as a JSON object of the form {"error":<code>}. The complete table, from the error reference:

CodeMeaning
0Successful operation (for logout, a successful exit)
1Invalid session
2Invalid service name
3Invalid result
4Invalid input
5Error performing request
6Unknown error
7Access denied
8Invalid user name or password
9Authorization server is unavailable
10Reached limit of concurrent requests
11Password reset error
14Billing error
1001No messages for selected interval
1002Item with such unique property already exists, or cannot be created according to billing restrictions
1003See the reason variants below
1004Limit of messages has been exceeded
1005Execution time has exceeded the limit
1006Exceeding the limit of attempts to enter a two-factor authorization code
1011Your IP has changed or session has expired

Error 1003 is five different failures wearing one number, and the only way to tell them apart is the reason field that accompanies it. The reference documents five variants: reason 1 means only one request is allowed at the moment, reason 2 carries the string LIMIT api_concurrent, reason 3 carries LAYERS_MAX_COUNT, reason 4 carries NO_SESSION, and reason 5 carries LOCKER_ERROR. Dispatch on the reason rather than on the code, and treat LAYERS_MAX_COUNT and LOCKER_ERROR as opaque — the reference lists the strings without expanding what they mean internally, so log them and alert on them rather than building behaviour on a guess.

Other codes carry a reason string too, and it is the difference between an actionable log line and a useless one. Error 4 means invalid input and nothing more until you read what came with it. A token of the wrong length answers with a reason of WRONG_TOKEN_LENGTH, and the message quota reports itself the same way with LIMIT msgs_activity attached to code 1004:

{"error":4,"reason":"WRONG_TOKEN_LENGTH"}
{"error":1004,"reason":"LIMIT msgs_activity"}

Log the reason verbatim alongside the code in every case. An integration that records only the numeric code will spend its first production incident guessing which of a dozen possible payload problems produced error 4.

Classify codes before you retry them

Retry logic that treats every failure the same way is the most expensive mistake available here, because two of the most common codes are terminal and retrying them consumes the exact resource that recovering would need. Five classes cover everything:

ClassCodesAction
Re-auth1, 1011, 1003 reason 4One token/login round trip, then replay the call once
Transient3, 5, 6, 9, 1003 reason 5Exponential backoff with jitter, capped attempts
Throttle10, 1003 reasons 1 and 2, 1004Long backoff and reduce in-flight concurrency
Narrow and retry1005Shorten the interval or reduce the units, then retry
Terminal2, 4, 7, 8, 11, 14, 1002, 1006, 1003 reason 3Dead-letter queue, no retry
Not an error1001An empty interval — return zero rows

Error 7 belongs in the terminal class because access is a property of the token’s flags, fixed at the moment the token was created, rather than a property of the request. The authorization form defaults access_type to 0x100, which grants online tracking only, so a token minted from a form that never set the parameter carries no view access and will return error 7 on data reads for as long as it exists. Retrying does not change the flag, and concurrent retries consume the session’s ten-simultaneous-request ceiling, which is what error 10 reports — so a mis-flagged token turns one configuration mistake into unrelated calls failing across the same session. The fix is to reissue the token: read-only is 0x100 combined with 0x200, which is 768 in decimal.

Error 1 also looks transient and is not. The session is invalid, and replaying the same request with the same session identifier returns the same code again; it needs a fresh token/login before the call can succeed. Cap that at one re-authentication per request, because a re-auth loop against a token that has actually been revoked walks straight into the login ceiling described below. Error 1005 deserves the same care in the opposite direction: the request exceeded its server-time budget, so a bare replay repeats the same timeout and spends the execution quota on the way. Narrow the interval, reduce the unit count or drop detalization instead.

Watch the login ceiling before you build a retry loop

The session and login quotas are the ones an integration is most likely to breach by accident, and the consequence reaches beyond the integration that caused it:

LimitValue
Failed logins per IP per minute10
Successful logins per IP per minute120
Active sessions of one user from one IP100
Active tokens per user1,000
Password reset attempts per minute1

Exceeding these produces a temporary IP-address block. That is why error 8 is the expensive terminal in the table above: more than ten failed logins from one address in a minute takes down every integration sharing that egress address, not only the one holding the bad credential. A worker that responds to a bad token by re-authenticating in a loop will reach the ceiling in under a minute and take its neighbours with it.

Budget message loading against five separate ceilings

Codes 1004 and 1003 exist because message loading is metered, and it is metered several ways at once rather than one. All of the following come from the current limitations page:

LimitValue
Loaded into all sessions of one user15,000,000 messages
Loaded by one user within 2 minutes15,000,000 messages
Imported within 1 minute500,000 messages
Loaded by one user within 1 hour200,000,000 messages
Message layers50
Messages on request2 GB

After a bound is reached the user cannot load or import messages for the remainder of that period, and the documentation notes that this breaks report execution and track building as well. The quota is attached to the user rather than to a feature, which is the part that surprises people: a backfill job saturating the two-minute window degrades the live interface running under the same account, and the operator experiencing it has no way to connect the symptom to the job. Give extraction work its own account where the customer’s licensing allows it, and pace it against the two-minute window rather than against wall-clock throughput.

Guard report results against the limit that returns nothing

Report execution has its own budget, and it fails in a way that no error code describes:

LimitValue
Online execution5 minutes of server time
Execution by notification5 minutes of server time
Execution by job10 minutes of server time
Rows in a report with detalization400,000
Continuous execution per user from one IP10 minutes, then reports cannot be requested for a further 10
AggregateA user cannot request more reports per hour than the system can execute in an hour

That continuous-execution rule is the one bulk extraction meets first, and it bites twice: exceeding it stops the current run and then locks reporting out for ten minutes, which turns a single oversized job into a twenty-minute hole in a backfill.

The reference is explicit about the boundary: when the time limit is reached, report execution is skipped and no results are returned. That is an absence rather than an exception. The call succeeds, the payload contains no rows, and an ETL that reads an empty result as an interval with no activity writes a plausible zero into the warehouse. Nobody notices until a customer disputes a number weeks later, at which point the gap is indistinguishable from a genuinely quiet period. Two guards are cheap enough to be unconditional: compare the returned row count against a baseline you know to be non-zero before writing anything, and treat an empty result over a period with known activity as a failure rather than as data.

This is also the point where the archived forum is worth citing. “Geofence export data doesn’t have info” accumulated 11,747 views before the board went offline, and it is one of a cluster of export and report threads that never resolved. Every forum URL now redirects to the help.wialon.com root rather than to a matching page, which Google’s own site-move guidance warns may be treated as a soft 404, and captured pages survive for roughly 61% of threads in the Wayback Machine.

Size concurrency to the session, not to your worker pool

The last group of quotas is the one that determines how much parallelism is available at all, and it is measured per session rather than per account or per process:

LimitValue
Heavy requests simultaneously per session3
API requests simultaneously per session10
Map tracings simultaneously per session3
avl_evts requests per 10 seconds per session10
core/check_unique requests per minute30
Tile rendering per IP200 seconds of server time
Tile rendering per IP per user120 seconds of server time
Largest integer safe in a double parameter9007199254740991 — use long above it

Message loading and report execution both count as heavy, so three concurrent extractions is the ceiling for a session no matter how many workers are pointed at it. Adding workers past that point does not increase throughput; it converts would-be work into error 10 and error 1003, which then consume retry budget. The avl_evts ceiling matters for the same reason in the opposite direction — an event loop polling once per second is already at the published limit before anything else is running.

  • Give each worker its own session rather than sharing one, so the three-heavy-request ceiling applies per worker instead of across the pool.
  • Record the reason string with every error, not only the code, or error 4 and error 1003 stay undiagnosable.
  • Alert on a zero-row report over a known-active interval, because the platform will not tell you that one happened.

Also in this reference

Contact

Let's connect.

About Us

Helping businesses to make their fleets safer, teams more productive and processes more efficient.