Trigger Scripts

Trigger scripts are attached to a database table or query. Trigger scripts are different from "transformation scripts", which are attached to an assay design and are intended for transformation/validation of incoming assay data.

Trigger scripts can be configured to run on a per-row basis whenever there is a insert/update/delete event on the table (with a few exceptions). They are called on a per-HTTP request basis (or in other contexts like ETLs), either before or after the request is executed. Typical uses for trigger scripts are (1) to alter incoming data or (2) to set off cascading changes in other tables.

Note that trigger scripts are not applied in the following contexts:
  • Importing Sample Sets
  • Importing a study or folder archive
  • Bulk importing datasets
  • Using a file watcher to import
  • Running an ETL
For a complete list of available contexts, see Availability of Server-side Trigger Scripts.


Trigger Script Location

The trigger script attached to a particular table needs be placed in the folder associated with the table's schema. The script must be named after its associated table or query. For example, a QUERY_NAME.js script would be placed in:

Data Classes:
Study Datasets:
Custom Schemas:

where MODULE_NAME, SCHEMA_NAME and QUERY_NAME are the names of the module, schema and query associated with the table. If you are building a java module or deploying your module from source, place the scripts within the /resources/ subdirectory of the module tree.

Order of Execution

When multiple trigger scripts are defined in different modules for the same table/dataset, they will be executed in reverse module dependency order. For example, assume module A has a dependency on module B and both modules have trigger scripts defined for myTable. When a row is inserted into myTable, module A's trigger script will fire first, and then module B's trigger script will fire.

Shared Scripts / Libraries

Trigger scripts can pull in functionality from other shared libraries.

Shared libraries should be located in a LabKey module as follows, where MODULE_NAME is the name of the module and SCRIPT_FILE is the name of the js file. The second occurrence of MODULE_NAME is recommended to avoid namespace collisions. The directory structure depends on whether or not you are building from source.

When building the module from source:

In a deployed module:

For additional information about module directory structure, see Map of Module Files.

In the example below, the 'hiddenVar' and 'hiddenFunc' are private to the shared script, but 'sampleFunc' and 'sampleVar' are exported symbols that can be used by other scripts.

shared.js (located at: myModule/resources/scripts/myModule/shared.js)

var sampleVar = "value";
function sampleFunc(arg)
return arg;

var hiddenVar = "hidden";
function hiddenFunc(arg)
throw new Error("Function shouldn't be exposed");

exports.sampleFunc = sampleFunc;
exports.sampleVar = sampleVar;

To use a shared library from a trigger script, refer to the shared script with the "require()" function. In the example below, 'require("myModule/shared")' pulls in the shared.js script defined above.

myQuery.js (located at: myModule/resources/queries/someSchema/myQuery.js)

var shared = require("myModule/shared");

function init() {

You can also pull in functionality from the following LabKey JavaScript libraries:

Access these libraries by using "require('labkey')":

To send an email:

var LABKEY = require("labkey");

function sendEmail()
var userEmail = "messagetest@validation.test";
// need a user to send email to/from
email: userEmail,
sendEmail: false,
containerPath: "/Shared/_junit"

var msg = LABKEY.Message.createMsgContent(LABKEY.Message.msgType.plain, "Hello World");
var recipient = LABKEY.Message.createRecipient(, userEmail);
var response = LABKEY.Message.sendMessage({

Note: The server-side Ajax methods are synchronous. These methods return immediately and the success/failure callbacks aren't necessary. The returned object is the same as the first parameter to either the success or the failure callbacks. To determine if the method call was successful, check the returned object for an 'exception' property.

Console API

A console API is provided for debugging purposes. Access using "require('console')":

var console = require("console");
console.log("** evaluating shared.js script");

The require() Function

The parameter to require() is a CommonJS module identifier (not to be confused with a LabKey module) without the ".js" extension. The path is absolute unless it starts with a "./" or "../" in which case it is relative. Relative CommonJS module identifiers can't be used by trigger scripts, but they can be used by other shared server-side scripts in the "scripts" directory.

Script Execution

The script will be evaluated once per request. In other words, any state you collect will disappear after the request is complete.

If your script runs for more than 60 seconds, the script will be terminated with an error indicating that it timed out.


  • init(event, errors)
  • complete(event, errors)
    • The init and complete functions are called once before or after insert/update/delete for a set of rows.
    • The event parameter is one of "insert", "update" or "delete".
    • The errors object for the init and complete functions is an array of error objects.
  • beforeInsert(row, errors)
  • beforeUpdate(row, oldRow, errors)
  • beforeDelete(row, errors)
  • afterInsert(row, errors)
  • afterUpdate(row, oldRow, errors)
  • afterDelete(row, errors)
    • Use these functions to transform and/or validate data at the row or field level before or after insert/update/delete.

Parameters and Return Values

  • row - The row that is being inserted, updated or deleted.
  • row.FIELD - A field in the row being inserted, updated, or deleted. Modifiable by the script.
  • errors - During the update/insert/delete process, you may add a message to this parameter to indicate that a field or an entire row has an error. Can be an array of errors. When any error messages are added to the error object, the insert/update/delete will be canceled.
  • errors.FIELD - The field that has the error. Can be an array to indicate that many fields have errors.
  • errors[null] - If you assign an error message to the null property of error, the message is returned for the entire row.
  • return false - Returning false from any of these functions will cancel the insert/update/delete with a generic error message for the row.

function beforeInsert(row, errors)
console.log("beforeInsert got triggered");
console.log("row is: " + row);
row.Email = "";
console.log("edited row is: " + row);

Sample Scripts #1

The sample module, testtriggers.module, shows how to attach a trigger script to a table/query. The actual trigger script merely returns the argument it is passed, this example illustrates the mechanism for adding and running scripts.

To run the sample:

  • Download the .module file: testtriggers.module.
  • Copy the .module file to the directory LabKey Server/externalModules/. (For developers who have downloaded the src code and are running the server --> stop the server --> put this .module file under <src code>/build/deploy/externalModules (create externalModules dir if you don't have it) --> re-start the server)
  • Turn on the JavaScript Console: (Admin) > Developer Links > Server JavaScript Console.
  • Enable the module in a folder.
  • Navigate to the the module-enabled folder.
  • Go to the Items table: (Admin) > Developer Links > Schema Browser > testtrigger > Items > View Data.
  • Insert a new record using (Insert Data) > Insert New Row.
  • On the server's internal JavaScript console ( (Admin) > Developer Links > Server JavaScript Console), monitor which trigger scripts are run.
  • Repeat by editing or deleting records.

Sample Scripts #2

Other sample scripts are available in the module "simpletest", which can be downloaded here:

If you want to install this module on a running server, ensure that you do not already have a module of this name. If you are building a local development machine, you may be including the test modules from the LabKey enlistment which contains a simpletest module with similar functions.

Unzip the module structure and review how the scripts and queries are structured to use as a model for your own development. The following sample scripts are included:

  • simpletest/scripts/simpletest/Debug.js - a script that will echo a trace log of arguments
  • simpletest/scripts/simpletest/ScriptValidationExports.js - a shared script that returns the arguments (or returns a message if called on a hidden function)
  • simpletest/scripts/validationTest/... - contains a set of trigger scripts that utilize the shared scripts and the LabKey libraries:
    • actionUrlTest.js
    • exportTest.js
    • filterTest.js
    • messageTest.js
    • queryTest.js
    • securityTest.js
    • simpleQueryTest.js
    • utilsTest.js
  • simpletest/queries/vehicle/colors.js - a largely stand alone trigger script. When you insert a row into the Vehicle > Colors query, it performs several format checks and shows how error messages can be returned.
  • simpletest/queries/lists/People.js - a largely stand alone list example. When you insert/update/delete rows in the People list, this trigger script checks for case insensitivity of the row properties map.

Related Topics


Was this content helpful?

Log in or register an account to provide feedback

expand all collapse all