White Papers
Abstract
When sending XML data to IBM Food Trust via the APIs, various errors can occur. This note describes the most common errors, their causes, and how to resolve them.
Content
Using the Food Trust API requires three different kinds of HTTPS calls: one to get an identity token from IBM Cloud, the second to use the IBM Cloud token to get a Food Trust onboarding token, and the third to submit your actual XML data using the onboarding token as proof of authorization. The onboarding token is valid for a number of hours, so you can use the same onboarding token again and again in the third type of HTTPS call to submit a number of different XML files, until the token finally expires. When the token expires, you must go back to the first step.
The general process is described in the Food Trust Developer Zone wiki, on these two pages:
https://github.com/IBM/IFT-Developer-Zone/wiki/How-To-Get-an-Authentication-Token-for-System-Users
https://github.com/IBM/IFT-Developer-Zone/wiki/how-to-upload-data-to-IBMFoodTrust
Various errors can occur at each stage of this process. This document describes some of the common errors. Note that the Dev Zone wiki uses the "curl" command to demonstrate how to make the HTTPS calls. You may instead be making the HTTPS calls from a program, using some HTTP client library, but the basic principles are the same. In all cases, you'll make an HTTPS request and you will receive an HTTP response code and response text in return.
The response code and text will tell you whether the call succeeded or failed. 200-series response codes like "200 OK" and "201 Created" indicate success; the response text will vary depending on which type of HTTPS call you're making. In general, any response code other than 200 or 201 is an error.
Note about curl: (6) Could not resolve host: application
Before we dive into the specifics of HTTP errors we must deal with this one. You can see it when using curl to test the Food Trust APIs if you fail to properly quote your curl command arguments. The curl commands typically start like this:
curl -X POST --header 'Content-Type: application/xml' ...
The quotes around the Content-Type are important since there's a space in that string. But different operating systems and different shells have different rules about quoting. For example, the 'single quotes' above work on Unix but not on Windows; Windows requires "double quotes" instead.
If you get an error like "curl: (6) Could not resolve host: application", it probably means that the quotes around 'Content-Type: application/xml' didn't work, and as a result curl interprets application/xml as the URL that you want to access -- that's why it says "Could not resolve host: application." The correct solution will depend on your OS and your command shell, but in general if you see "Could not resolve host: application", that means that your quotes are having no effect.
Incorrect URL
Any of the HTTP commands could return a "404 not found" response code, with response text like:
"Requested route ('xiam.ng.bluemix.net') does not exist.
This usually means that the URL you are trying to access, is invalid. (In this example I added a leading 'x' to the URL for the IBM Cloud identity service.) It could also mean that there's some fundamental problem with the service you're trying to reach -- for example, the IBM Cloud identity service could be down, or unreachable from your network. But the most common cause of this error by far is simply that you've typed an incorrect URL.
No User-Agent header
If you use any of the Food Trust HTTP API's and your request does not include a User-Agent header, you will receive a "403 server refused" error. By default, the curl command automatically supplies a User-Agent header like "curl/7.29.0" but if you are using another means of making your HTTP requests, then you may have to explicitly set the User-Agent header, as described here .
Non-existent API key
The first HTTPS command, used to get an identity token from the IBM Cloud identity service, requires you to submit an API key that belongs to some service ID that you have previously set up in IBM Cloud. If you submit an API key that is not known to IBM Cloud, then you'll get a response code of "400 Bad Request" and response text like this:
{"context":{"requestId":"3594523101","requestType":"incoming.OIDC_Token","userAgent":"curl/7.29.0","clientIp":"129.42.208.184","url":"https://iam.ng.bluemix.net","instanceId":"tokenservice/2","threadId":"18caf8","host":"localhost","startTime":"05.09.2018 11:44:01:113 UTC","endTime":"05.09.2018 11:44:01:178 UTC","elapsedTime":"65","locale":"en_US","clusterName":"iam.ng.bluemix.net"},"errorCode":"BXNIM0415E","errorMessage":"Provided API key could not be found"}
Failure to submit an IBM Cloud service token
Once you've obtained an IBM Cloud service token via the first HTTPS request, your next step is to use it to request an IBM Food Trust onboarding token. If you attempt to obtain an onboarding token without submitting an IBM Cloud service token, then you'll get a "400 Bad Request" response code, and response text like this:
{"rc":400,"error":"access_token missing in post."}
Incorrect organization ID, or service ID does not belong to your organization
When requesting an onboarding token in the second HTTPS call, you supply your organization ID as part of the URL, like this:
https://fs-identity-proxy.mybluemix.net/exchange_token/v1/ organization/8aa24278-1627-4ec6-8231-a4f6e28ebec9
Here 8aa24278-1627-4ec6-8231-a4f6e28ebec9 is your organization ID. As part of the setup process for Food Trust automation, you should have created a service ID in IBM Cloud, and added that service ID as a System User on the IBM Food Trust User Management page. You submit an API key that belongs to the service ID, in your first HTTPS call. If that API key is valid but actually belongs to a service ID that is not registered as a System User for your organization, then your second HTTPS call will fail; you will get a "404 Not Found" response code, and response text like this:
{"ok":false,"statusCode":404,"error":"User Id: serviceid-44037041-3742-4b32-bc12-76987054237c not found with solution Id: 51882f96-4168-4660-af83-759a528966a1 and organization Id: 8aa24278-1627-4ec6-8231-a4f6e28ebec9"}
The problem here might be that you submitted the wrong organization ID, or that your service ID is not registered as a Food Trust System User for your organization. You can check both of those things via the User Management screen.
Note for internal IBM users: notice the "solution ID" in the error message. This is the ID for the specific instance of Food Trust that you're using. There are multiple instances of Food Trust at IBM: in addition to the production instance, there are various other instances used by Development and for demos. If you target your HTTPS request to the wrong instance of Food Trust (for example, if you use an API key that belongs to a Production organization, but you aimed your HTTPS request at the Development instance) then you'll get the error message above.
Invalid (malformed, corrupted, expired) IBM Cloud service token
If you submit an IBM Cloud service token that has been corrupted in some way, or has expired, then you will get an HTTP response code of "400 Bad Request" in the second HTTP call, when you try to submit the service token to IBM Food Trust. You will also get response text like this:
{"ok":false,"statusCode":400,"error":"sub field not found by token introspection. The token is invalid or may have expired."}
No bearer token when submitting an XML file
Once you've made the second HTTPS call to get a Food Trust onboarding token, you're ready to submit XML files via the third HTTPS call, using that onboarding token as proof of authorization. If you attempt to make that third HTTPS call to submit an XML file without including an onboarding token, then you get an HTTP response code of "401 Not authorized" and response text like this:
{"message":"Not Authorized: Missing Token."}
Incorrect method of specifying onboarding token when submitting an XML file
When you submit an XML file via the third HTTPS call, you must supply the onboarding token that you received from the second HTTPS call. That second HTTPS call returns a JSON structure, and the onboarding token is one element inside that JSON structure. If you supply the entire JSON structure rather than just the onboarding token string, then you will get a "401 Unauthorized" response code from the third HTTPS call, and response text like this:
{"message":"Not Authorized: Unable to read JSON value: ?v?j?b??G?{"alg":"RS256","typ":"JWT","kid":"pbsa-prod.us-south.containers.mybluemix.net/d260f5aa-40b4-4deb-8855-0a5cff34462b/onboarding""}
Invalid / malformed / corrupted Food Trust service token
As mentioned previously, when you submit an XML file via the third HTTPS call, you must supply the onboarding token that you received from the second HTTPS call. If the onboarding token is malformed in some way, then you get either a "401 Unauthorized" or a "500 Internal Server Error" response code (depending on the type of damage that was done to the onboarding token), and response text like:
{"message":"Not Authorized: JWT strings must contain exactly 2 period characters. Found: 0"}
or:
{"timestamp":"2018-09-05T12:14:16.554+0000","status":500,"error":"Internal Server Error","exception":"io.jsonwebtoken.SignatureException","message":"JWT signature does not match locally computed signature. JWT validity cannot be asserted and should not be trusted.","path":"/ift/api/connector/fs/connector/v1/assets"}
Expired Food Trust service token
The Food Trust service token that you get from the second HTTPS call is valid for a number of hours, and it can be used over and over again during that time, to submit multiple XML files to Food Trust. Eventually however the token will expire. When that happens, you will get a "401 Not authorized" repsonse code if you continue to use the expired token, and response text like this:
{"message":"Not Authorized: JWT expired at 2018-09-01T02:20:26Z. Current time: 2018-09-04T22:58:57Z, a difference of 333511732 milliseconds. Allowed clock skew: 0 milliseconds."}
When this happens, you must go back to the first step and get a new identity token from IBM Cloud, and then use it to get a new Food Trust service token. Then use the new service token to re-submit the XML file again.
Invalid XML submitted to Food Trust
If you do everything right with respect to authentication and authorization and you have valid tokens, but you submit an XML file that contains invalid content (i.e. that is illegal XML format) then you will receive a "400 Bad Request" response code, and response text like this:
{"message":"Could not read XML input. com.ctc.wstx.exc.WstxParsingException: Unexpected close tag </ns2:DocumentIdentification>; expected </ns2:StandardBusinessDocumentHeader>.\n at javax.xml.stream.SerializableLocation@4a0eae6","traceId":"5d92b7bc-3489-4410-b7b6-25198e0b9e63"}
In this case I deliberately removed an open tag on one of the XML elements. As you can see, the error response tells you which specific XML elements it found to be in error.
Invalid Food Trust ID format
Your XML files will contain Food Trust IDs to identify products and locations and etc, and these IDs must be in certain specific formats. If you submit an incorrectly-formatted Food Trust ID (inside a properly-formatted XML file -- so the XML structure is valid, but the Food Trust data inside is not what was expected), then you will get a "400 Bad Request" response code, and response text like this:
{"message":"tradeItemData[0].gtin Type must match one of the following patterns: [GS1_GTIN, FTPI]. Visit this url to look up the pattern error codes. https://github.com/IBM/IFT-Developer-Zone/wiki/api-Error-Messages\n","traceId":"e26ad187-dfa1-432d-8b5e-ecc435a0c13a"}
In this example, I deliberately mis-formatted an IBM Food Trust product ID (a so-called "FTPI" as mentioned in the response text). Notice that the response text points to a web page where all of the formats are defined in detail. Additionally, the response tells you where in the XML file the error occurred (tradeItemData[0].gtin is the <gtin> element in the first <tradeItemData> element). So to solve this, you would look at the relevant <gtin> in the XML file, and compare it to the GS1_GTIN and FTPI formats from the Developer Zone wiki page.
Bad entitlement mode
You can specify an "entitlement mode" setting for each XML file that you submit to Food Trust; you do this via a particular HTTPS header. If you specify a mode that is not one of the valid entitlement modes, then you will get a "400 Bad Request" response code, and response text like this:
{"message":"foo is not a valid IFT-Entitlement-Mode header value!"}
Bad check digit
Each GS1 identifier that you submit in your XML files has a check digit (typically the last digit of the ID) which helps to prevent errors. If you specify a GS1 ID that has an incorrect check digit, then you'll get a "400 Bad Request" response code, and response text like this:
{"message":"tradeItemData[0].gtin.CheckDigit 10108025219019 has an invalid check digit expected 10108025219012\n","traceId":"bac5e8f9-a0c1-4e90-8f56-aa539a63980b"}
Notice that the error message tells you which entry in your XML file had a problem. The error above is basically telling you that 10108025219019 is not a valid GTIN, because the final digit (the check digit) is wrong.
Was this topic helpful?
Document Information
Modified date:
12 November 2018
UID
ibm10730487