example-app Errors 

Each error returned by the example-app API has a specific error code string starting with GGT_ that identifies the exact error that caused the API call to fail. These codes are intended to be searchable -- you should find information on them on this page, but you can Google them too. Error codes are also helpful to Gadget support engineers when trying to help you correct an error, so please include them when communicating with Gadget staff if possible!


A request was made to act on a model that provided invalid data for that model. Validity is determined by the model's validations as configured in the Editor, so this can happen if you make a call without required data, or pass data that doesn't pass a configured RegExp validation, or data that doesn't pass a custom code validation for example. More information can be found in the Action Result Format section of the documentation for the model action you are trying to invoke.

The invalid fields and the validation error messages suitable for showing to a user can be determined by looking at the validationErrors field of the GraphQL response, or the validationErrors of the InvalidRecordError Error object thrown by the generated JavaScript client.

1import { InvalidRecordError } from "@gadget-client/example-app";
2import { api } from "../my-api-setup";
3try {
4 await api.exampleModel.create({ name: undefined }); // try to create an example model without a required field
5} catch (error) {
6 if (error instanceof InvalidRecordError) {
7 // `error.validationErrors` is an array of { apiIdentifier: string, message: string } objects describing which fields of the model were invalid
8 console.warn(error.validationErrors); // outputs => [ { apiIdentifier: "name", message: "is required" } ]
9 }
1mutation {
2 createExampleModel(exampleModel: { name: null }) {
3 success # will be false
4 errors {
5 # all errors have a code and a message
6 code
7 message
8 # we can look at the typename of the error to know which class of error it was specifically
9 __typename
10 # Get the validation errors on the InvalidRecordError type, if it is one. There can be other error types, so not all errors will have the `validationErrors` property. Gadget uses a GraphQL interface here to allow asking for these properties where needed.
11 ... on InvalidRecordError {
12 validationErrors {
13 apiIdentifier
14 message
15 }
16 # other fields available on the invalid record error
17 record # the record which failed validation
18 model {
19 apiIdentifier # the details of the model this error was thrown for
20 }
21 }
22 }
23 }


Thrown when the server encounters data that is not unique despite the existence of unique validation on a field. If encountered, it is likely that you added a unique validation to a field that has duplicate data and the validation is in an errored state.


While logging in Gadget encountered an error while saving the user on the newly authenticated session. If encountered, double check the user has the correct permissions to view or manipulate data in example-app.


A request was made to an application that successfully authenticated, but Gadget was unable to store the authenticated user's information because there was no session to store it on. This happens when authentication attempts are made using a request to the Gadget API that doesn't send cookies, or when using API keys for authentication against the example-app API.

If you're using API Key authentication (see the Authentication docs, you shouldn't (and can't) login those clients. API Key authenticated clients prove their identity by passing the API key itself, and get their roles right from the API Key as opposed to any one user. Currently, Gadget does not support API Key based authentication that acts as or masquerades as a particular user.

If you're using Browser Session Authentication (see the Authentication docs), you must ensure that your GraphQL client is storing and sending cookies as you make requests. If you're using fetch in a web browser for example, you need to ensure you pass the credentials: "include" option to the fetch call to include the cookies that power Session Cookie authentication. For more information on the options that fetch takes, see the MDN Fetch docs.


Too much time was taken to execute an action. Actions and Global Actions are given 3 minutes to execute all effects. See the Actions guide for more details.


An invalid action was taken on a record, and there could be no transition to the model's state. This is most likely because the action you are trying to take does not exist, check for typos.


Gadget tried to read a record from the database whose stored data is no longer valid according to the current schema for the model. For example, a record was written with null for a given field, and then a Required validation was added to that field, rendering the record invalid. Gadget can't read the record and return data that doesn't conform to the schema that's been configured, so this error is thrown.

This can happen for a few reasons:

  • a new field was added to a model and marked as required before being set for existing records
  • new validations were added to an existing field, and records had already been saved with that field
  • a field's type was changed and then marked as required without data being set for existing records

To fix this error, you can either remove the offending validation from the model's schema (usually, make the field no longer required until all the records have a value set), or you can remove the offending data from the database.

Note: Records that throw this error when accessed via the high level GraphQL API can still be accessed via the Internal API for your application. The Internal API won't throw this error when reading records.


An API request failed to authenticate via the API Key method because an incorrect or invalid API key was passed in the Authorization header. This can be because the API Key was deleted, was misspelled, or was improperly passed in the HTTP Authorization header. Consult the Authentication docs for more information on authenticating via an API Key.


Gadget supports full ACID transactions via its GraphQL over WebSockets API, or using the api.connection.transaction function. GGT_INCORRECT_TRANSACTION_SEQUENCE errors are returned when the startTransaction, rollbackTransaction, or commitTransaction mutations are called in the incorrect order, or outside a WebSockets connection to the Gadget API. If you're using the generated JS client for example-app, the api.connection.transaction handles the correct ordering of each transaction calls automatically, so we recommend using it where possible.

There's a few different common patterns that can cause this issue:

  • calling the transaction fields via a normal GraphQL-over-HTTP request. Gadget doesn't support this -- you need to invoke these fields via a WebSocket connection.
  • calling the transaction fields out of order. To process a transaction, you must startTransaction before doing any mutations, and then you must either commitTransaction or rollbackTransaction to complete the transaction. Closing the websocket connection automatically rolls back the open transaction
  • accidentally running more than one transaction at once. This can happen if you're using the generated Gadget client and opening .transaction functions in async or parallel code. You can't use the same WebSockets connection to process simultaneous transactions. You can open multiple WebSocket connections, or run your transactions one at a time to avoid this.


Gadget supports full ACID transactions via it's GraphQL over WebSockets API and has a limit for each transaction's duration of 5 seconds. Gadget wraps all run effects in a transaction, so all of them must complete within this 5 second window to avoid timing out and throwing this error. If you'd like to do something long running, like making an external HTTP call, it's best to do that as a success effect so that the important part of the work is completed and committed first.

There's many things that can result in slow effects, like:

  • making HTTP calls within run effects on an action
  • fetching or trying to mutate too many related records in an effect
  • uploading files or streaming data to and from the disk or an external service
  • doing any very demanding computations like evaluating an ML model

To avoid this issue, ensure your effects complete quickly.


Gadget applications are backed by a scalable Postgres database that can handle thousands of concurrent operations and transactions. When under load, or when asked to perform a particularly slow query, the backend database can take too long to execute it and threaten the health of the application. Gadget won't allow any individual query to run for longer than 3 seconds. Queries that take too long are aborted and this error is thrown. This can affect both reads and writes.

There's many things that can result in slow queries, like:

  • fetching many relationships of a model at the same time
  • fetching many records for a model at the same time
  • having too many rows of data stored for the same model.

To try to make your queries fit within the timeout, you can adjust a few things:

  • fetch fewer relationships at a time, or fewer relationships of relationships
  • fetch a smaller page size (with the first and last arguments to a GraphQL call)
  • split up large tables into smaller ones

Query performance optimization can be a challenging task, so if you're stuck and would like some help, feel free to join us in the Gadget Discord to talk through your specific issue!


This error is thrown when API calls try to query or mutate records by ID that don't exist. If you try to invoke an action on a record ID that no longer exists (or never existed) in the database, you'll see this error code. It can also arise from trying to find a record by a field value (using the .findByX field finders in the generated API client) where no record exists for that field value.

Avoid this error by ensuring you don't try to act on deleted records, or checking if a record exists by querying for it before trying to act on it.

Finders can be adjusted to use .findByX finders if you expect the record to exist, or findMany({filter: { field: "some-value"}}) finds if the record may not exist.


This error is thrown when an API call tries to execute validations configured on a model, and one of those validations is not yet configured, or configured incorrectly. API calls to this model can't be processed until the validation is correctly configured, which can be done in the Gadget Editor for the model in question.

Common causes of this error code are:

  • a string length or number range validation without a minimum or a maximum set
  • an invalid RegExp pattern for a RegExp validation

The specific error message for this error should refer to which type of validation is causing the issue, and which model field the misconfigured validation is on.


This error is thrown when an API call is made that invokes something the caller doesn't have permission to do. Resources in Gadget are all protected by an access control system that only allows callers to read or write data they have been granted permission to access via their roles. GGT_PERMISSION_DENIED means the caller does not have a role which can access some bit of accessed data.

GGT_PERMISSION_DENIED errors don't return a lot of data to the caller to prevent leaking information about the system's access control system or helping attackers gain access, but, they do log details about why permission was denied to the application's logs. If you're encountering this error and can access the Gadget application's internal logs, you can see the following error properties:

  • actorRoleKeys: which role keys the actor has been granted. Role keys are set differently for different actors in the system, see the Access Control guide for more information.
  • resource: which resource the request was trying to access but denied access to. The resource can be a:
    • model record read, which will look like resource: { model: "widget", read: true }
    • actions on models, which will look like resource: { model: "widget", action: "create" }
    • global actions, which will look like resource: { globalAction: "syncShopify" }
  • actor: what the request actor was determined to be. The actor for a request can be:
    • an API key, which will look like actor: { apiKey: "gsk-some-api-key" }
    • a logged in user or session within your application , which will look like actor: { model: "user", { id: 123 } or actor: { model: "session", record: { id: 123 } }
    • a logged in developer working on the application, which will look like actor: { developer: true, id: 123, email: "[email protected]" }
    • the Gadget platform itself running calls, which will look like actor: { platform: true }.


This error is thrown by the Gadget platform when something unexpected goes wrong within the platform itself during the processing of your request. This error is the platform's fault, and generally can't be actioned by developers. We realize this error can be frustrating and we take great care to avoid the root causes of it by keeping our infrastructure in tip top shape. If this error is plaguing you, please reach out to us and we can work with you to correct the root cause.


This error is thrown by the Gadget platform when something unexpected goes wrong when executing your code. If an error is thrown during any custom code, Gadget is unable to discern exactly why the error happened, so it produces this code. This error code can come from custom code effects or custom code validations.


This error is thrown when a field is set up incorrectly inside Gadget. Different fields require different bits of data in order to function properly, so if you are getting this error when trying to run GraphQL queries, ensure the field doesn't have any problems associated with it.

Most often, this error is thrown for misconfigured relationship type fields, like belongs to, has many, has many or has one when the are missing key information. All relationships need to have the related model set up correctly, so if that has never been set, or if the related model has been deleted, the relationship field can't be accessed.

To configure a relationship, you must select the related model, and fill out any other required information in the relationship configuration form. GraphQL schema generation cannot continue until the relationship has been configured correctly.


This error is thrown when a Gadget requires an action to be present but cannot find it. This often happens when Gadget is asked to perform a high level task that requires some actions to be run, like a _converge nested action invocation or processing a webhook payload from a third party service. By default, models have a create, update, and delete action that Gadget can use to implement these high level tasks, but if you have deleted one of those actions, Gadget can't perform the high level task. To remedy this, restore the default actions that the model might need, or avoid triggering the high level task.

For models provided by a Connection, removing models and then reinstalling the connection will reset changed models back to their original state, restoring any deleted actions.


This error is thrown when a Gadget is asked to perform a high level task that requires some fields to be present in a model's schema, like syncing a connection, but the fields are missing. This can happen if you've deleted a field from a model, or if a connection has been upgraded and requires new fields to exist. To remedy this, restore any deleted fields to models mentioned in the error message.

For models provided by a Connection, removing models and then reinstalling the connection will reset changed models back to their original state, restoring any deleted fields.


This error is thrown when a Gadget is asked to perform a high level task that requires some fields to be present on a record, but the fields are missing. This can happen if you've created or updated records using the Internal API that Gadget expects to be a certain way.

For records that are missing data, if you have the data, you can fix them by making API calls to update the records, or you can delete the erroneous records if you no longer need them.


An invalid argument value was given to some field in the query. For example, the in filter for model queries must not be an empty array.


An invalid action name was given to the example-app API. For example, a nested action was provided that doesn't actually correspond to an action in the application. The client making the request will have to be updated to ensure they reference an action that exists.


An unknown type was encountered while processing the input params schema from one of your custom code effects. You should find the file specified in the error message and see if there's a typo or unsupported type in the input params schema that is described by module.exports.params. Gadget currently supports simple object and scalar types from JSON Schema.


A request was sent to Gadget that needed to be authenticated but there was no session to authenticate in scope. This is most likely due to a user querying for the current session while using an API key as their authentication method. If access to the currentSession is needed for authentication purposes, switch the authentication mode to use cookies instead. Find more information in the Authentication guide.


A request was sent to Gadget that tried to authenticate, but the request specified an authentication mode which Gadget doesn't recognize. The valid authentication mode strings are browser-session, api-key and internal-auth-token.


This error is thrown when a code snippet is either missing a configured source file or the source file is pointing to an invalid file path. This can be remedied by ensuring that the code effect or validation in question has a valid code snippet path selected in the Gadget Editor.


A json field has a default value configured that isn't a valid JSON string. The developer must provide a valid JSON for the default string so Gadget can apply it to new records.


This error is thrown when we receive 401 Unauthorized when accessing Shopify on your behalf. This can happen when we sync a shop that has uninstalled your app. To remedy this, you can click the "Force Uninstall" button next to the affected shop on the shop installs page.


Apps built in JavaScript use the standard package.json file to manage dependencies installed from npm, as well as the packages Gadget generates like the API client. If the package.json file is not valid JSON, your application can't run, and Gadget can't edit the file. Fix this error by correcting the JSON parse error in package.json.


In order to protect the Gadget platform, each Gadget application has a limited capacity for executing actions or serving an application's HTTP routes. This error is returned if there are more than 300 concurrent such requests. API clients receiving this error can retry the request after a short time to wait for more backend resources to be available.


Right after they're created, Gadget applications finish setting themselves up in the background by installing dependencies and bootstrapping all the required infrastructure under the hood. This error is thrown when a request is made to a Gadget application before this background work has been completed as the application is not yet ready to serve requests. To avoid this error, wait until the application has finished setting up. Background application setup generally takes no longer than 30s.


This error is thrown when the store in question has an unpaid due(s). According to the Shopify spec this 'frozen' state goes into effect after the bill's due date. Some reasons as to why the payment may have failed on Shopify is listed in this Shopify Spec.


This error is thrown when the Gadget app is unable to communicate with your Shopify store. Typically in cases like these the recommended steps to fix are...

  1. Attempt to contact the store owner.
  2. Uninstall & Reinstall the app on Gadget (potentially force uninstall if the Shopify store no longer exists or the owner is unreachable).
  3. Contact Shopify.


This error is thrown when there is a problem communicating with the Shopify API. The first step to approach remedying this issue is to investigate the Gadget logs for any relevant or detailed information and moving on from there. If nothing of the obvious becomes apparent from the logs then consider the following. Store's marked by Shopify as Fradulent, Frozen, Cancelled will return this error on the Gadget client - as such investigate this as a potential catalyst.


This error is thrown when Shopify returns a 403 from an API request. Often, this is related to your app missing permissions for <GuidesRelativeLink path="/connections/shopify#protected-customer-data">protected customer data</GuidesRelativeLink>.