Skip to content
Developerhome
X3

Troubleshooting and Coding Guide

  Less than to read

1. Overview

This guide focuses on failure modes, bad patterns, and how to correct them. It complements the structural reference (Classes and Representations Guide). Use it when something breaks, behaves inconsistently, or you are refactoring older scripts.

2. Typical breaking patterns

2.1 Scoping issues

Calling Gosub METHODS (or referencing AMETHOD) inside $EVENTS fails because AMETHOD is not declared in $EVENTS. Each label only sees its own allowed variables.

Bad example in Sage X3 4GL (runtime failure due to bad reference to AMETHOD):

STD_DO_SOMETHING:
  # Work only with passed-in parameters (avoid CURPTH / AMETHOD)
  # ...
Return
$METHODS
  # Here AMETHOD is in scope
  Case AMETHOD
    When "DO_SOMETHING"             : Gosub STD_DO_SOMETHING
    When Default
  Endcase
Return

$EVENTS
Case [L]CURPTH
  When ""
    Case AEVENT
      When "AQUERY_TRANS_AFTER"     : Gosub STD_DO_SOMETHING
      When Default                  : Gosub METHODS            # ❌ AMETHOD not in scope here
    Endcase
  Endcase
Return

Fix it

  1. Keep calls inside labels that declare the variables they need.
  2. Extract shared logic into a parameter-only subroutine, or
  3. Create an intermediate label that sets the needed variable then calls the routine.

Corrected pattern, fixes the above code:

STD_DO_SOMETHING:
  # Work only with passed-in parameters (avoid CURPTH / AMETHOD)
  # ...
Return
 
$METHODS
  # Here AMETHOD is in scope
  Case AMETHOD
    When "DO_SOMETHING"         : Gosub STD_DO_SOMETHING
    When Default
  Endcase
Return
 
$EVENTS
Case [L]CURPTH
  When ""
    # DO NOT call METHODS expecting AMETHOD; instead, call the generic routine directly
    Case AEVENT
      When "AQUERY_TRANS_AFTER" : Gosub STD_DO_SOMETHING
      When Default              # ✅ Safe
    Endcase
  Endcase
Return

2.2 Inside $METHODS

Do not rely on ACTION or CURPTH inside $METHODS. They are not guaranteed. Use only AMETHOD (and explicit parameters). If you need CURPTH, run that logic in $EVENTS or pass it in.

2.3 Representation differences

Some representation scripts omit $OPERATIONS. That is valid. Never invoke $OPERATIONS unless it exists and declares AOPERATION.

3. Migration checklist

Run these steps per script during modernization:

  1. Verify allowed labels:
    • Classes: $EVENTS, $PROPERTIES, $METHODS, $OPERATIONS
    • Representations: $EVENTS, $PROPERTIES, $METHODS
  2. Add and manage EVENT_NOT_EXECUTED in $EVENTS.
  3. Add and manage PROPERTY_NOT_EXECUTED in $PROPERTIES.
  4. Remove cross‑label variable access (e.g. AMETHOD in $EVENTS).
  5. At label start, consult AINFO.EXCLUDED; skip if listed.
  6. When unused: set exclusion flag and append to AINFO.EXCLUDED.
  7. For dimensioned properties:
    • Linked to a collection: keep legacy pattern.
    • Not linked & persistent: rely on internal array (no forced collection link).
  8. Test after each label refactor (small diffs reduce risk).

4. Allowed variables quick reference

(Primary table lives in the Classes and Representations Guide; reproduced here for convenience.)

Context Allowed variables
$EVENTS CURPTH, AEVENT
$PROPERTIES CURPRO, ARULE
$METHODS AMETHOD
$OPERATIONS (classes only) AOPERATION

Representations do not always have $OPERATIONS.

Common fixes summary

Problem Symptom Fix
Cross-label variable use Random empty values / failed branches Refactor to parameterized subroutine
Calling METHODS from $EVENTS Runtime failure (missing AMETHOD) Call a neutral shared routine instead
Repeated unused event/property checks Performance drag Use EVENT_NOT_EXECUTED / PROPERTY_NOT_EXECUTED + AINFO.EXCLUDED
Hidden dimension overhead Slower access Use internal array for non-collection dimensioned properties

Final tips

  • Stay inside each label’s declared scope.
  • Centralize reusable logic into parameter-based subroutines.
  • Use exclusion flags early to skip dead hooks.
  • Keep diffs small: migrate one label at a time.