Troubleshooting
What a failed request looks like, how to read it, and fixes for the failures that come up most often.
Error responses
Section titled “Error responses”Every failed request returns a JSON body. There are two shapes, and you tell them apart by one thing: whether details is present.
detailspresent — the error came from the service, andcodeis the numeric gRPC status code.detailsabsent — the error came from the gateway, before the request reached the service, andcodeis a copy of the HTTP status.
The same rule holds for 4xx and 5xx.
A service error:
{ "code": 3, "message": "validation failed", "details": [ { "@type": "type.googleapis.com/google.rpc.BadRequest", "fieldViolations": [ { "field": "playerid", "description": "required" } ] }, { "@type": "type.googleapis.com/google.rpc.RequestInfo", "requestId": "1ff721182e0466bb3657575ef53c19ad" } ]}A gateway error:
{ "code": 401, "message": "Jwt is missing" }Status codes
Section titled “Status codes”| HTTP | code |
gRPC code | When |
|---|---|---|---|
400 |
3 |
INVALID_ARGUMENT |
Validation failed. Carries BadRequest — read fieldViolations. |
400 |
9 |
FAILED_PRECONDITION |
The request is well-formed but the state it needs is not there — e.g. a device referencing a location that does not exist. |
401 |
401 |
— | Missing, malformed or expired token. From the gateway, so no details. |
403 |
7 |
PERMISSION_DENIED |
Authenticated, but not allowed this resource or namespace. |
404 |
5 |
NOT_FOUND |
The addressed resource does not exist. |
409 |
6 |
ALREADY_EXISTS |
The resource is already there under a different identity. |
500 |
13 |
INTERNAL |
Server-side failure. Safe to retry with backoff. |
Reading a validation failure
Section titled “Reading a validation failure”google.rpc.BadRequest carries one entry per rejected field.
field — where it went wrong
Section titled “field — where it went wrong”The proto field path, which is snake_case — not the camelCase you sent in the request body:
| Example | Means |
|---|---|
playerid |
a top-level field |
location.external_id |
dotted for nested messages |
0.availability |
index first for an entry in a repeated field |
description — why it went wrong
Section titled “description — why it went wrong”Always begins with one of these words, optionally followed by ": " and a specific explanation:
| Prefix | Means |
|---|---|
required |
Missing. An *_UNSPECIFIED enum value counts as missing. |
invalid |
Present but not acceptable — e.g. invalid: products requires a device with SENSOR_BASKET. |
conflict |
Clashes with something already stored. |
not found |
Names something that does not exist. |
not ready |
Exists, but not in a state that allows this. |
unknow |
Unclassified failure. (Spelled without the trailing n.) |
Branch on field plus the leading word, not on the full string — the text after ": " is explanatory and may change.
requestId
Section titled “requestId”google.rpc.RequestInfo.requestId is the trace id for the request, and it rides every service error. Log it, and quote it to us when raising something — it is how we find your request.
There is no ErrorInfo, so there is no stable machine-readable reason or domain to switch on. BadRequest.fieldViolations[] is the machine-readable part.
Common problems
Section titled “Common problems”Error invalid_client or invalid_grant on the token request
Section titled “Error invalid_client or invalid_grant on the token request”Your client_id or client_secret is wrong. Double-check both, and make sure the @ in the client ID is URL-encoded as %40 in the form body.
Error no namespace provided
Section titled “Error no namespace provided”The X-Verve-Namespace: project:<PROJECT_ID> header is missing. Add it to every Inventory API request.
401 Unauthorized
Section titled “401 Unauthorized”Your access token is missing, expired, or malformed. Confirm the Authorization: Bearer <access_token> header is set, and request a fresh token if the current one has expired — see Authentication.
403 Permission Denied
Section titled “403 Permission Denied”Authentication succeeded but the request isn’t authorized. Either your service account lacks permission on the project, or the X-Verve-Namespace header is missing or incorrect. Verify it is set to project:<PROJECT_ID>.