Troubleshooting Error Messages
A reference for the errors returned during an LTI® launch or by the LTIAAS API. Find the code or message you received below.
It's not necessary to decode JWTs, inspect the OIDC handshake, or verify signatures to resolve these errors. LTIAAS performs the protocol work. A failure at the protocol level is normally caused by a configuration value — a URL, a client ID, a service permission, or a server clock — and is corrected in the LMS or in the LTIAAS Portal.
Error Code Index
| Code | Cause | Fixed in |
|---|---|---|
DUPLICATE_NONCE | Launch submitted twice | Retry |
ERROR_RETRIEVING_KEYSET | Key set unreachable | LMS |
IDTOKEN_NOT_FOUND | Launch record expired | Your app |
INACTIVE_SERVICE | Service not on your account | Portal |
INVALID_BEARER_AUTHORIZATION_HEADER | Bad header or API key | Your app |
INVALID_LINE_ITEM_ID_FOR_CONTEXT | Line item from another context | Your app |
INVALID_LTIK_AUTH_AUTHORIZATION_HEADER | Bad header, API key, or expired ltik | Your app |
INVALID_REDIRECT_URI_PARAMETER | Launch URL not registered | LMS |
INVALID_SERVICE_AUTH_AUTHORIZATION_HEADER | Bad header, API key, or service key | Your app |
INVALID_SERVICE_ENDPOINT_URL | Malformed endpoint from the LMS | LMS |
KEYSET_INCORRECTLY_FORMATTED | Key set is not a valid JWKS | LMS |
LINE_ITEM_ID_INCORRECTLY_FORMATTED | Malformed line item ID | Your app |
MONTHLY_TRIAL_ACTIVE_USERS_QUOTA_REACHED | Trial user limit | Portal |
MONTHLY_TRIAL_LAUNCH_QUOTA_REACHED | Trial launch limit | Portal |
MONTHLY_TRIAL_OAUTH_ACCESS_TOKEN_QUOTA_REACHED | Trial token limit | Portal |
PUBLIC_KEY_NOT_FOUND_IN_KEYSET | Signing key not published | LMS |
SERVICE_NOT_AVAILABLE_FOR_CONTEXT | Service not granted for this launch | LMS |
UNREGISTERED_OR_INACTIVE_PLATFORM | No matching registration | Portal |
Errors without a code are listed under Messages Without an Error Code.
How to Read an Error Response
Errors returned by LTIAAS are JSON objects containing status, error and details. A response that is not JSON, or that lacks these fields, did not come from LTIAAS.
The details object takes one of three forms.
| Form | Identified by | Meaning |
|---|---|---|
| Validation error | details.errors array | A request parameter was missing or invalid |
| Service error | details.message code | See the code index above |
| Forwarded LMS error | details.externalError | The request reached the LMS and the LMS rejected it |
A service error also carries details.description, which distinguishes causes that share a code. Some carry service, keysetUrl, providedUrl or kid.
A forwarded LMS error carries externalUrl (the endpoint called), bodySent (what LTIAAS sent) and bodyReceived (what the LMS returned):
{
"status": 422,
"error": "Unprocessable Entity",
"details": {
"message": "HTTP Request error: Request failed with status code 422",
"externalUrl": "https://lms.example.com/api/lti/courses/1/line_items",
"bodySent": { },
"bodyReceived": { },
"externalError": true
}
}
bodySent records the exact payload sent to the LMS. When an LMS reports a required field as absent, this field shows whether it was sent, which is the information the LMS support team needs.
Error Codes
DUPLICATE_NONCE
400 Bad Request
Cause. Each launch carries a single-use value that cannot be replayed. The same launch was submitted twice, usually by a double click, a page refresh, or an iframe loading twice.
Fix. Perform a new launch. If it occurs on every launch, the LMS is repeating requests and its administrator should investigate.
ERROR_RETRIEVING_KEYSET
400 Bad Request · details.keysetUrl
Cause. LTIAAS could not retrieve the key set used to verify messages from the LMS.
Fix. Open keysetUrl in a browser. If it does not return JSON containing a keys array, the URL in the registration is wrong. If it loads in a browser but not for LTIAAS, the cause is usually an incomplete TLS certificate chain: the intermediate certificate must be bundled with the server certificate on the host serving the key set.
IDTOKEN_NOT_FOUND
401 Unauthorized
Cause. The launch referenced by the token is no longer stored. Launch records are retained for approximately 25 hours.
Fix. Use a serviceKey for operations that run outside a live launch. See Accessing the API asynchronously.
INACTIVE_SERVICE
403 Forbidden · details.service
Cause. The service is not enabled on your LTIAAS account. service is one of Deep Linking, Names and Roles, Assignment and grades, Dynamic Registration or OAuth.
Fix. Add the service to your account in the Portal.
This is distinct from SERVICE_NOT_AVAILABLE_FOR_CONTEXT, which means the service is enabled on your account but was not granted by the LMS.
INVALID_LINE_ITEM_ID_FOR_CONTEXT
400 Bad Request
Cause. The line item ID is well formed but belongs to a different context than the launch used to authenticate the request.
Fix. Retrieve line item IDs for the current context rather than caching them globally. See Manipulating grade lines.
INVALID_REDIRECT_URI_PARAMETER
400 Bad Request
Cause. The URL being launched is not present in the tool's registered redirect URLs. The LMS may report this as "Redirect Uri must match one of the registered Redirect URL values".
Fix. The values must match as exact strings; a trailing slash present in one and absent in the other is sufficient to fail. Confirm the Target Link URI is correct and that the identical value appears in the redirect URL list.
INVALID_SERVICE_ENDPOINT_URL
400 Bad Request · details.providedUrl, details.service
Cause. The LMS supplied a service endpoint that is not a valid URL.
Fix. This is malformed data from the LMS. Report providedUrl and service to the LMS support team.
KEYSET_INCORRECTLY_FORMATTED
400 Bad Request · details.keysetUrl
Cause. The key set was retrieved but is not a valid JSON Web Key Set.
Fix. Confirm that keysetUrl returns a JSON object containing a keys array. If it returns HTML, an error page, or a single key, the URL in the registration is wrong.
LINE_ITEM_ID_INCORRECTLY_FORMATTED
400 Bad Request
Cause. The line item ID sent is not in the expected format.
Fix. Use IDs returned by the API rather than constructing them. See Manipulating grade lines.
PUBLIC_KEY_NOT_FOUND_IN_KEYSET
400 Bad Request · details.keysetUrl, details.kid
Cause. The key set was read but does not contain the key the LMS signed with. kid identifies the key that was looked for.
Fix. The LMS is signing with a key it has not published. Ask the LMS administrator to confirm the key set is current, then perform a new launch.
SERVICE_NOT_AVAILABLE_FOR_CONTEXT
403 Forbidden · details.service
Cause. The service is enabled on your account, but the LMS did not make it available for this launch. LTI® allows a platform to grant services per course or per placement, so the same tool can have a service in one course and not another.
This is also returned when the launch granted access to a single line item but not to the line item container, in which case scores can be submitted but line items cannot be listed or created.
Fix. The LMS administrator must enable the service for that course or tool placement. No change on the LTIAAS side will grant it.
A permission granted in the LMS applies only to subsequent launches. After it is changed, perform a new launch and regenerate any stored serviceKey, as the existing one was issued under the previous permissions.
UNREGISTERED_OR_INACTIVE_PLATFORM
400 Bad Request
Cause. The LMS could not be matched to a platform registration. An LMS identifies itself with its url and clientId, and both must match the registration exactly.
Fix. Check, in order:
- A trailing slash present in the
urlin one system and absent in the other. - A space or hidden character in the
clientId. Check the value in an editor that displays invisible characters. - A registration that exists but has not been activated. Activate it in the LTIAAS Portal.
- On Canvas, an incorrect
url. Canvas sends a different issuer than expected — see the Canvas registration guide.
Authorization Header Codes
401 Unauthorized
Three codes cover the authentication methods, and each is returned with more than one description. Read details.description to identify the cause.
| Code | Description | Cause |
|---|---|---|
INVALID_LTIK_AUTH_AUTHORIZATION_HEADER | Invalid API Key for account. | The API key is wrong |
INVALID_LTIK_AUTH_AUTHORIZATION_HEADER | Invalid or expired ltik. | The ltik is wrong or expired |
INVALID_SERVICE_AUTH_AUTHORIZATION_HEADER | Invalid service key. | The service key is wrong |
INVALID_BEARER_AUTHORIZATION_HEADER | Authorization header doesn't match… | The header format is wrong |
Fix. A description referring to the accepted format means the header itself is malformed rather than the credentials being wrong. See Authenticating API requests for the accepted formats. A common cause is sending the API key alone to an endpoint that requires both the API key and the ltik.
Expired ltik. The ltik expires 24 hours after the launch that generated it, so a request made after that window fails even when unchanged. For operations outside a live launch, such as scheduled grade submission, use a serviceKey, which does not expire. See Accessing the API asynchronously.
Trial Quota Codes
403 Forbidden · details.description
Cause. A free trial account reached a monthly limit: MONTHLY_TRIAL_LAUNCH_QUOTA_REACHED, MONTHLY_TRIAL_ACTIVE_USERS_QUOTA_REACHED or MONTHLY_TRIAL_OAUTH_ACCESS_TOKEN_QUOTA_REACHED.
Fix. Upgrade the account.
Validation Errors
400 Bad Request · details.errors
Cause. A request parameter was missing or invalid. Every failing field is listed:
{
"status": 400,
"error": "Bad Request",
"details": {
"errors": [
{ "field": "scoreMaximum", "message": "Missing 'scoreMaximum' parameter." }
]
}
}
Fix. Compare the request against the API reference and correct the listed fields.
Messages Without an Error Code
| Message | Cause | Fixed in |
|---|---|---|
"message": "Forbidden" | Blocked by the web application firewall | LTIAAS support |
lti_message_hint is missing | Wrong access token endpoint in the registration | LMS |
| The token can't be used before DATE | The LMS server clock has drifted | LMS |
| 401 during dynamic registration | The LMS could not retrieve its registration token | LMS |
| Authlogic validation error | Canvas is not creating secure sessions | Canvas |
| Unknown Key Type | Canvas cannot use the tool's key | Canvas |
invalid_client | The LMS rejected the token request | LMS |
unauthorized_client | The registration lacks the scope | LMS |
| Signature verification failed | The launch signature did not verify | LMS |
errorId with a 500 | A failure inside LTIAAS | LTIAAS support |
A Bare Forbidden Message
A body containing only "message": "Forbidden", without status or details, comes from our web application firewall, which blocked the request before it reached the API. Common reasons:
- The request originated from a bare IP address. LTIAAS requires a fully qualified domain name; for local testing use a tunnelling service such as ngrok.
- The request contained content identified as malicious, such as SQL in query parameters, code in the body, or calls to paths that are not documented endpoints.
- The source IP address appears on a public blocklist.
Serverless platforms are a frequent cause, as their outbound IP addresses change regularly. Contact support with your API key so that traffic can be allowed by key rather than by IP address.
A Missing lti_message_hint
A 400 reporting that lti_message_hint is missing usually means the LMS registration specifies an incorrect access token endpoint, preventing the LMS from completing the step that generates the hint. On Canvas this is commonly the authorization redirect URL used in place of the token URL.
Ask the LMS administrator to verify the access token endpoint against the platform's documentation.
The Token Can't Be Used Before DATE
The LMS determined that a token was issued at a future time, which means its server clock has drifted. The clock must be within a few minutes of NTP time for tokens to validate. Ask the LMS server administrator to synchronise it against time.google.com.
A 401 During Dynamic Registration
If manual registration succeeds but dynamic registration fails with a 401 and a missing registration token, the cause is the LMS server's network path rather than the registration data: the LMS could not complete its own request for the token. Firewall rules or security group configuration on the LMS host are the usual cause.
Third-Party Cookies Are Being Blocked
Browsers increasingly block third-party cookies, which prevents sessions from being created inside an iframe. See managing third-party cookies with LTI®.
Internal Server Errors
A 5xx response containing only an identifier indicates a failure inside LTIAAS:
{
"status": 500,
"error": "Internal Server Error",
"details": { "errorId": "8f3c2a1b9d7e" }
}
These are logged and monitored automatically and cannot be resolved from your side. Send us the errorId if one is blocking your integration.
Authlogic Validation Error: You did not provide any details for authentication.
This appears in the Canvas server logs rather than the browser, and means Canvas is not creating secure user sessions. The same cause presents as the user being returned to the Canvas login screen after having already logged in.
Copy config/session_store.yml.example to config/session_store.yml and set secure to true, as described in this Canvas issue:
development:
session_store: encrypted_cookie_store
expire_after: 86400 # 1 day in seconds
- # secure: true
+ secure: true
See also the Bitnami Canvas caution, which accounts for a significant proportion of reported Canvas problems.
Unknown Key Type
Returned by Canvas rather than by LTIAAS, during registration or on the first launch.
Cause. The Canvas instance cannot use the tool's public key. In nearly every reported case this is a self-hosted Canvas that lacks the provisions LTI® requires — most often the Canvas image packaged by Bitnami on AWS.
Fix. See the Bitnami Canvas caution, which links the community thread describing the changes that image needs. On a hosted Canvas instance, check that the key was entered complete and unwrapped.
invalid_client and unauthorized_client
OAuth 2.0 errors returned by the LMS token endpoint when a service call requests an access token. They come from the platform, so the text and detail vary by vendor.
Cause. invalid_client means the platform would not accept the client assertion — usually the client ID does not match the registration, or the platform could not verify the assertion against the tool's published key set. unauthorized_client means the client is known but not permitted the grant or scope it asked for.
Fix. For invalid_client, confirm the client ID on the registration and that the key set URL is reachable from the LMS. For unauthorized_client, the registration has not been granted the service scope, which an LMS administrator changes — see INACTIVE_SERVICE for the case where the service is disabled on the LTIAAS side instead.
Signature Verification Failed
Cause. The launch signature did not verify against the platform's published keys. Usually the platform rotated its signing key and something is serving a stale copy, or the key set URL on the registration points somewhere that is no longer correct.
Fix. Confirm the key set URL on the registration resolves and returns a key set containing the kid from the failing launch. A rotation that resolves on retry needs no action; one that persists means the registration is pointing at the wrong key set. Compare with PUBLIC_KEY_NOT_FOUND_IN_KEYSET, which is the same problem detected on the LTIAAS side.
Contacting Support
Contact support@ltiaas.com when the LMS returns HTML instead of a valid LTI® response, when a 500 returns an errorId, when the firewall is blocking requests that should be allowed, or when a launch fails and none of the checks above account for it.
Include:
- A HAR file of the failing launch, which records what the LMS sent.
- The complete error response, including
details, and in particularbodySentandbodyReceivedwhenexternalErroris present. - The LMS and the course the launch originated from, as services are granted per context.
Common questions
How do I read an LTIAAS error response?
Every error has a status, an error code and a details object. The shape of details depends on the kind of failure — a list of field errors for validation, a message for a service error, or the LMS's own response under externalError when the failure came from the platform.
What does an errorId mean?
It identifies a failure inside LTIAAS itself, recorded on our side. Nothing in your configuration will fix it. Send the errorId to support and it can be traced directly.
Why does the same integration work in one course and fail in another?
Services are granted per context. A tool can hold grade or roster permissions in one course and not another, which produces a service error in one place and success in another with no code difference.
What should I include when contacting support?
A HAR file of the failing launch, the complete error response including details, and which LMS and course it came from. The HAR carries the redirect chain, which is usually where the cause is.
