Skip to main content
Kodexa uses GoJA, a Go-based JavaScript engine, for server-side scripting across the platform. Scripts can validate uploads, route workflows, react to data changes, and compute dynamic dropdown options.

Runtime Characteristics

GoJA supports ES5 with partial ES6 features including arrow functions, template literals, let/const, and destructuring. However, it is synchronous only — there is no support for async/await, Promises, or event loops.
Key constraints:
  • Sandboxed — no filesystem access, no network access (except via service bridges)
  • No module system — no require() or import
  • Synchronous — all calls are blocking; no callbacks or timers
  • Deterministic — same inputs always produce same outputs

Execution Contexts

Scripts run in different contexts depending on where they are configured. Each context has its own timeout, globals, and intended purpose.

Core Globals

These functions are available in all scripting contexts.

log

Write messages to the platform execution log via leveled methods. Each method is variadic and joins arguments with spaces.
Supported methods: log.debug, log.info, log.warn, log.error.

console.log()

A convenience wrapper that joins arguments with a space and writes at debug level.

Document API — ScriptDocument

The ScriptDocument object represents a loaded Kodexa document (KDDB). It is available as document in intake scripts and returned by loadDocument() in script steps.
Do not call doc.close() from platform scripts. Kodexa persists modified documents and releases script document resources after the script completes.

Example: Querying a Document

Data Object API — ScriptDataObject

Data objects represent extracted entities (invoices, line items, claims) within a document. They form a tree structure with parent-child relationships.
getFirstAttributeValue() returns the current typed value, not the original extracted text. The value precedence is: stringValue > decimalValue > booleanValue > dateValue (RFC 3339) > raw value.

Example: Reading and Writing Attributes

Data Attribute API — ScriptDataAttribute

Data attributes store individual typed values on a data object. Each attribute has a tag name, optional typed values, and audit trail tracking.
No-op suppression: Writes that do not actually change the value are automatically suppressed and will not trigger downstream recalculation. This uses epsilon comparison for decimals (1e-9) and time.Equal() for dates. You do not need to guard against redundant writes.
For most write paths, prefer currentObject.setAttribute(name, value) over fetching the attribute first and calling typed setters. setAttribute finds-or-creates the attribute and picks the type-appropriate setter automatically.
Type resolution. Both setAttribute and addAttribute resolve the new attribute’s TypeAtCreation in the same precedence order:
  1. opts.type (advanced override on addAttribute)
  2. A runtime-supplied TaxonResolver (browser subscriptions wire one)
  3. The document’s cached taxonomies — taxonomies travel with the document via the KDDB
  4. A fallback inferred from whichever typed-value field the caller supplied (e.g. decimalValueDECIMAL, stringValueSTRING)
Scripts can extend the in-scope set at runtime with document.addTaxonomy(taxonomy) — the next write call sees the new taxonomy.Numeric taxon types — NUMBER, INTEGER, DECIMAL, CURRENCY, and PERCENTAGE — all share the underlying DecimalValue slot and are routed there automatically. Don’t pass type: "DECIMAL" on numeric writes; the resolver picks the right slot from the taxon.
addAttribute ignores the path option. Attribute paths are derived from the parent data object + tag name, so path (if supplied) is discarded and the call logs a warning. Drop path from existing addAttribute calls. To control where an attribute lives, navigate to the correct parent via getOrCreateChild(...) first, then call addAttribute on that parent.

Example: Updating an Attribute

Content Node API — ScriptContentNode

Content nodes represent the structural elements of a document’s content tree: pages, lines, words, tables, and cells.

Example: Searching Content Nodes

Context-Specific Details

Intake Scripts

Intake scripts run when a file is uploaded to a document store. Use them to validate, classify, or route incoming files.

Script Steps

Script steps run inside Activity Plans and can load documents, call service bridges, invoke LLMs, and read the knowledge resolved on the in-scope family.
For dispatch logic driven by upstream knowledge resolution (vendor routing, processing-model selection, etc.), use the knowledge global instead of re-deriving it from data objects. See Knowledge Bindings.

Event Subscriptions

Event subscriptions run in response to attribute changes on data objects within a taxonomy. They are configured on the Event Subscriptions tab of the taxonomy editor.

Selection Option Formulas

Selection option formulas compute dynamic dropdown values for data form fields. They can call service bridges and reference attributes.

Best Practices

Guard against null values. In event subscriptions, always check that currentObject exists before accessing it. In any context, attribute lookups may return null or undefined.
Prefer setAttribute for writes. currentObject.setAttribute(name, value) finds-or-creates the attribute and routes through the type-appropriate setter. Reach for the typed setters (setStringValue, setDecimalValue, etc.) only when you already hold an attribute reference and need fine-grained control.
Keep scripts focused. Each script should have a single, clear purpose. Complex logic is better split across multiple steps or event subscriptions.
Be aware of timeouts. Intake scripts have 5 seconds, script steps have 15 seconds, and event subscriptions and option formulas have only 2 seconds. Avoid unnecessary loops or redundant document loads.
No async operations. GoJA does not support Promises, async/await, setTimeout, or setInterval. All code runs synchronously. If you need to call an external API, use the serviceBridge global.
Debugging tip: Use log.debug(...) liberally during development. Debug-level messages appear in the execution log but do not affect production behavior. Remove or reduce logging once the script is stable.

Common Patterns

Null-safe Attribute Access

Iterating Children

Conditional Attribute Creation

setAttribute is idempotent — it finds-or-creates the attribute. There is no need to check whether it already exists.

Date Comparisons

Troubleshooting

Script timeout exceeded — Your script is taking too long. Reduce iterations, avoid loading large documents unnecessarily, and move complex logic to module-based processing.
undefined is not a function — You are calling a method that does not exist in the GoJA runtime. Check for typos and verify the method is available in the API tables above. Remember: no Array.map(), Array.filter(), or other ES6+ array methods.
null reference errors — Always check return values before calling methods on them. getAttributeByName(), getParent(), selectFirst(), and similar methods can return null.
Writes not taking effect — Prefer currentObject.setAttribute(name, value) for writes; it routes through the type-appropriate setter and triggers downstream recalculation correctly. The no-op suppression logic only applies to typed values, so writing through setValue() with a stale type may silently no-op.