Skip to main content

Error handling

Exit codes​

The c8y binary has the following exit codes to indicate the success of the command. The exit codes include either information about command usage errors or the HTTP status code returned by the Cumulocity API call associated with the command.

General exit codes​

The following exit codes are general codes which relate to the usage of c8y commands.

Exit codeTypeDescription
0SuccessNo error occurred
2CancelledUser cancelled the command or did not confirm a prompt
99Unexpected errorUnknown error
100System ErrorUnexpected error when processing a command. i.e. can not write to a file, parsing error etc.
101User ErrorUser/command error such as invalid arguments
102No session loadedThe user has not selected a Cumulocity session yet
103BatchAbortedWithErrorsThe batched job was aborted due to too many errors
104BatchCompletedWithErrorsThe batched job completed but has 1 or more errors
105BatchJobLimitExceededThe batched job was stopped due to exceeding the total of allowed jobs though no other errors occurred
106Command timed outThe command took longer than the timeout setting
107Invalid aliasThe command took longer than the timeout setting
108Decryption errorError occurred when decrypting a session, i.e. invalid passphrase

HTTP status code errors​

The HTTP status code have been mapped to exit codes. To ensure compatibility with multiple operating systems, the exit codes are limited to values between 0 - 128. Therefore the HTTP status codes have been mapped to the following exit codes.

Note: Only HTTP status codes between 400 and 599 are mapped to exit codes. HTTP status 200 and 201 are classed as ok, and therefore will return an exit code of 0.

Exit codeStatus codeDescriptiondescription
1401StatusUnauthorized401Authentication has failed, or credentials were required but not provided.
3403ForbiddenYou are not authorized to access the API.
4404Not FoundResource not found at given location.
5405Method Not AllowedThe employed HTTP method cannot be used on this resource (e.g., using "POST" on a read-only resource).
9409Update Conflict or DuplicateThe entity already exists in the data source. or the entity already exists in the data source.
13413Execution TimeoutQuery had been running too long and was timed out.
22422Invalid DataGeneral error with entity data format.
29429Too Many RequestsIf the request rate limit per second is exceeded, the requests are delayed and kept in queue until the queue number limit is exceeded in which case the request is terminated with an error.
40400Bad RequestThe request could not be understood by the server due to malformed syntax. The client SHOULD NOT repeat the request without modifications.
50500Internal Server ErrorAn internal error in the software system has occurred and the request could not be processed.
52502Bad GatewayThe server, while acting as a gateway or proxy, received an invalid response from the upstream server
53503Service UnavailableThe service is currently not available. This may be caused by an overloaded instance or it is down for maintenance. Please try it again in a few minutes.

Handling errors (Shell)​

Errors which are related to command usage (not server errors), are written to standard error, while server responses (error or otherwise) are written to standard output.

For example, the following code tries to retrieve an non-existent managed object (id=0).

response=$( c8y inventory get --id=0 )
code=$?

if [ $code -ne 0 ]; then
echo "An error occurred: code=$code"
else
echo "ok"
fi

Output

2021-04-13T08:24:58.484+0200    ERROR   serverError: Finding device data from database failed : No managedObject for id '0'! GET https://test-tenant.example.com/inventory/managedObjects/0: 404 inventory/Not Found Finding device data from database failed : No managedObject for id '0'!
An error occurred: code=4

Silencing specific HTTP status codes​

Errors and warnings will be written to stderr. This means in the previous example the response variable will be empty, and an error message will still be displayed on the console (as no stderr redirection is being used).

You can silence specific error output for specific status codes by using the silentStatusCodes=xxx,yyyy option. The previous example can also be written as a one-liner:

c8y inventory get --id=0 --silentStatusCodes=404,409 && echo "ok" || echo "an error occurred code=$?"
Output
an error occurred code=4

The most common use-case for this is when you are creating something and you don't want to see an error message if the item already exists.

For example, let's say that are creating users but some users might already exist. You just want to be sure that after the script has been run the user is there (regardless when it was created).

user=$( c8y users create --userName=myexampleuser --template "{ password: _.Password() }" --silentStatusCodes 409 --select userName -o csv || c8y users get --id myexampleuser --select userName -o csv )
if [[ -n "$user" ]]; then
echo "OK: $user: "
else
echo "Unexpected error"
fi

Include error in response​

If you would like to return the error as json, then the --withError option can be given which will return any errors as a json response where individual fields can be parsed by using jq, or any other json parser.

# Note: stderr is redirected to null so it is not printed to the console
c8y inventory get --id=0 --withError 2>/dev/null | jq
Output
{
"errorType": "serverError",
"message": "Finding device data from database failed : No managedObject for id '0'!",
"statusCode": 404,
"exitCode": 4,
"url": "/inventory/managedObjects/0",
"c8yResponse": {
"error": "inventory/Not Found",
"message": "Finding device data from database failed : No managedObject for id '0'!",
"info": "https://cumulocity.com/guides/reference/rest-implementation/#a-name-error-reporting-a-error-reporting"
}
}

Handling errors (PowerShell)​

All PSc8y commands can be tested if they were successful or not by checking the PowerShell variable $LASTEXITCODE.

This variable stores the exit code from the last call to the binary (in this case the c8y binary).

So to check if a command was successful, the just check the $LASTEXITCODE value.

New-ManagedObject -Name "my object" -Force

if ($LASTEXITCODE -ne 0) {
Write-Error "Something went wrong!"
}

Example: Handling specific errors based on the exit code​

Let's say that your are writing a script to create an external identity for an existing device and you don't care if the external Id already exists (as it indicates that your script has already been run on this device).

Instead of first checking if the device has the external id, you can combine the requests into a single request and check the exit code for to determine if it already exists or was created.

The following shows an example of this using a file called create-identity.ps1.

[cmdletbinding()]
Param(
# Serial number. This must be unique!
[Parameter(Mandatory = $true)]
[string] $Device,

# Serial number. This must be unique!
[Parameter(Mandatory = $true)]
[string] $SerialNumber
)

# try to create the new id (store the error messages, and silence them because we want to handle within our script)
$response = New-ExternalId `
-Device $Device `
-Type "mySerial" `
-Name $SerialNumber `
-WithError

# Save the code for better re-use (in case something else updates it unexpectedly)
$Code = $LASTEXITCODE

# Handle the different outcomes
switch ($Code) {
0 {
# 0 -> No errors
Write-Host "Success: Created new identity. name=$SerialNumber" -ForegroundColor Green
}

9 {
# 9 -> Status code 409 : Duplicate/conflict
# In this case, this is still ok, but the message will be shown in a different colour
Write-Host "Success: Identity already existed. name=$SerialNumber" -ForegroundColor Yellow
}

3 {
# 3 -> Status code 403 : Permission denied
Write-Error "Failed: You do not have the correct ROLE to create an external identity"
}

Default {
# Handle unknown error
$ErrorDetails = $c8yError[-1]
Write-Error "Failed due to some other error! code=$_, details=$($response.message)"
}
}

The script can be called using the following command

./create-identity.ps1 -Device 12345 -SerialNumber 7DHD875d501SS
Output
Success: Created new identity. name=7DHD875d501SS

Success: Identity already existed. name=7DHD875d501SS

Failed: You don not have the correct ROLE to create an external identity

Failed to Some other error occurred! code=22, details=.....