Skip to main content
Axiom Strategy Lab Pro

Diagnostics & Error Codes

Strategy Lab diagnostics are the messages the engine shows when it cannot safely run your YAML, or when it can run but wants you to notice something about the way a rule behaved.

Written By Axiom Admin

Last updated 4 months ago

Diagnostics and Error Codes

Strategy Lab diagnostics are the messages the engine shows when it cannot safely run your YAML, or when it can run but wants you to notice something about the way a rule behaved.

The plain version: errors stop the strategy. Warnings do not. But warnings still matter. A warning can explain why a trade did not fire, why a token was unavailable during warm-up, or why a field you wrote has no practical effect.


Strategy Status

The status line tells you whether the engine is allowed to trade.

Status

Meaning

Strategy Active

No retained warnings or blocking errors were found.

Strategy Active with Warns

The strategy can trade, but one or more warnings were recorded. Read them before trusting the backtest.

Strategy Inactive

The strategy is blocked by an error or by required user consent/settings. It will not trade until the blocking issue is fixed.


Diagnostic Table

The on-chart table is meant to be read left to right:

Column

What to do with it

Severity

Fix ERROR first. Review WARN before trusting the result.

Reason

Starts with the stable diagnostic code, then shows the YAML location, problem, expression when relevant, and suggested repair.

A message usually looks like this:

EXPR_VALUE_UNAVAILABLE
Long Entries > PULLBACK_ENTRY > Entry Trigger
EMA_20 is not available during warm-up.
Expr: CROSS_OVER(PRICE_CLOSE, EMA_20)
Fix: Use NZ(EMA_20, fallback) or add a warm-up gate.

Every retained diagnostic should include a Fix: line. Known diagnostic codes use code-specific repair guidance. If a future or unknown code appears, the table falls back to documentation guidance instead of leaving you with a code and no next step.

Read the location line as the path back to your YAML:

Long Entries > PULLBACK_ENTRY > Entry Trigger

means:

In the Long Entries section,
inside the entry named PULLBACK_ENTRY,
the entry_trigger_when field produced the diagnostic.

The table only retains a limited number of messages. Fix the first issues, reload or let the strategy reprocess, then read the next retained messages.


Errors vs Warnings

Severity

Blocks trading?

What it usually means

ERROR

Yes

The engine cannot safely parse, validate, compile, or evaluate something required.

WARN

No

The engine handled the situation, but the result may not be what you intended.

INFO

No

Informational context. This is less common in the public table.

Warnings are not decoration. If a warning says a token was unavailable during warm-up, the engine probably used a typed fallback so the strategy could keep running. That may be exactly fine, or it may explain why an early signal stayed quiet.


Warm-Up, Lookbacks, and Unsafe Math

Most confusing diagnostics come from three different situations that look similar on the chart but need different fixes.

A token is warming up

Custom tokens from indicators can be NaN until the indicator has enough bars to calculate. For example, an EMA_20 token may not be usable at the beginning of the chart.

This can warn:

entry_trigger_when:
  CROSS_OVER(PRICE_CLOSE, EMA_20)

If it is safe to substitute price until the EMA exists, put the fallback directly around the token:

entry_trigger_when:
  CROSS_OVER(PRICE_CLOSE, NZ(EMA_20, PRICE_CLOSE))

If the rule should not even try until enough bars exist, add a warm-up gate:

entry_trigger_when:
  BAR_INDEX > 20
  && CROSS_OVER(PRICE_CLOSE, EMA_20)

Use this pattern for codes such as EXPR_VALUE_UNAVAILABLE when the problem is an unavailable token.

A lookback does not exist yet

On bar 0, PRICE_CLOSE[5] does not exist. On bar 3, it still does not exist.

This can warn:

entry_trigger_when:
  PRICE_CLOSE > PRICE_CLOSE[5]

Use NZ on the lookback value:

entry_trigger_when:
  PRICE_CLOSE > NZ(PRICE_CLOSE[5], PRICE_CLOSE)

Or gate the rule until the lookback can exist:

entry_trigger_when:
  BAR_INDEX > 5
  && PRICE_CLOSE > PRICE_CLOSE[5]

Use this pattern for EXPR_HISTORY_UNAVAILABLE.

A denominator can be zero or missing

Division, modulo, percent-from, and percent-change logic need a usable denominator. This is where SAFE_DIV belongs.

This can warn:

entry_trigger_when:
  PERCENT_CHANGE(PRICE_CLOSE, PRICE_CLOSE[5]) > 0.10

Put the safety inside the calculation:

entry_trigger_when:
  SAFE_DIV(
    PRICE_CLOSE - NZ(PRICE_CLOSE[5], PRICE_CLOSE),
    NZ(PRICE_CLOSE[5], PRICE_CLOSE),
    0
  ) * 100 > 0.10

Use this pattern for EXPR_DIVISION_BY_ZERO, EXPR_MODULO_BY_ZERO, EXPR_PERCENT_BASE_INVALID, and EXPR_PERCENT_PREVIOUS_INVALID.

Do not blindly wrap everything in SAFE_DIV. It only solves denominator problems. For missing tokens or missing lookback values, start with NZ or a warm-up gate.


YAML Codes

YAML diagnostics happen while the engine parses and validates your configuration.

Code

Severity

What happened

Usual fix

YAML_MISSING_REQUIRED_FIELD

Error

A required field is missing or unusable.

Add the field shown in the diagnostic.

YAML_INVALID_FIELD_VALUE

Error

A field has a value the schema does not accept.

Use a supported enum, number, boolean, or expression.

YAML_UNKNOWN_FIELD

Warn

The parser found a field it does not recognize.

Fix the typo or remove the field.

YAML_DUPLICATE_NAME

Error

Two units create the same name or state-token base.

Rename one unit so the sanitized names are unique.

YAML_REMOVED_FIELD

Error

YAML field was removed.

Use the latest YAML specification from the documentation.

YAML_UNKNOWN_REFERENCE

Error

A unit points at a setup or name the parser cannot find.

Fix spelling or create the referenced unit.

YAML_ALLOCATION_TOTAL

Error

Combined entry allocation percentage in one direction exceeds 100%.

Reduce entry allocations until the combined total is 100% or less.

YAML_ORDER_PRICE_REQUIRED

Error

The order type needs a price field.

Add the required limit or stop price expression.

YAML_ORDER_PRICE_FORBIDDEN

Error

A price field was supplied where it does not apply.

Remove the extra price field or change order type.

YAML_OCA_TYPE_NO_GROUP

Warn

An entry has OCA type but no OCA group.

Add entry_oca_group, or remove entry_oca_type.

YAML_CANCEL_NO_EFFECT

Warn

Cancel logic was added to a market order.

Remove the cancel field, or use a working order type.

YAML_VALIDATION_ERROR

Error

The parser emitted a generic blocking validation message.

Read the message text and treat it as a schema error.

YAML_VALIDATION_WARN

Warn

The parser emitted a generic non-blocking validation message.

Read the message text and remove ambiguity from the YAML.

Example: unknown field

- entry_name: PULLBACK_ENTRY
  entry_trigger_when: CROSS_OVER(PRICE_CLOSE, EMA_20)
  entry_allocation_percent: 50
  entry_order_typo: MARKET

entry_order_typo should be entry_order_type.

Example: order price mismatch

- entry_name: MARKET_PULLBACK
  entry_trigger_when: CROSS_OVER(PRICE_CLOSE, EMA_20)
  entry_order_type: MARKET
  entry_limit_price: PRICE_CLOSE * 0.99
  entry_allocation_percent: 50

Market entries do not use entry_limit_price. Either remove the price field or change the order type to LIMIT.


Expression Codes

Expression diagnostics happen while the parser compiles or evaluates a condition, price, or numeric field.

Code

Severity

What happened

Usual fix

EXPR_EMPTY

Error

A required expression is empty.

Write the missing condition or price expression.

EXPR_INVALID_HISTORY

Error

A history reference is malformed.

Use TOKEN[5] with a non-negative whole-number offset.

EXPR_UNKNOWN_TOKEN

Error

The expression references a token the engine does not know.

Check spelling, custom token setup, and state-token names.

EXPR_UNKNOWN_FUNCTION

Error

The function name is not recognized.

Use a supported uppercase parser function.

EXPR_UNSUPPORTED_FUNCTION

Error

The function exists conceptually but is not supported here.

Rewrite using supported parser functions.

EXPR_NAMESPACE_UNSUPPORTED

Error

Namespaced calls such as ta.sma() are not accepted.

Remove the namespace. Use supported parser functions when available, or pass indicator values in as custom tokens.

EXPR_ARITY

Error

A function received the wrong number of arguments.

Check the function signature.

EXPR_TYPE_MISMATCH

Error

A value had the wrong type for the operation.

Use a boolean, number, or comparison where required.

EXPR_STACK_UNDERFLOW

Error

The evaluator did not receive enough operands.

Check operators, function arguments, and parentheses.

EXPR_EVAL_STACK

Error

Evaluation ended with an invalid stack state.

Simplify the expression and check missing operators.

EXPR_MISMATCHED_PARENTHESES

Error

Parentheses are unbalanced.

Add or remove parentheses.

EXPR_MISMATCHED_TERNARY

Error

A ternary expression is incomplete.

Check condition ? true_value : false_value.

EXPR_DIVISION_BY_ZERO

Warn

Division attempted to use zero or an unusable denominator.

Use SAFE_DIV or provide a non-zero fallback denominator.

EXPR_MODULO_BY_ZERO

Warn

Modulo attempted to use zero or an unusable denominator.

Avoid modulo until the denominator is valid.

EXPR_FINAL_TYPE

Error

The final expression returned the wrong type for the YAML field.

Use a comparison for boolean fields or a numeric expression for price/quantity fields.

EXPR_HISTORY_UNAVAILABLE

Warn

A lookback value does not exist yet.

Use NZ(LOOKBACK, fallback) or gate with BAR_INDEX.

EXPR_VALUE_UNAVAILABLE

Warn

A token, function, or expression produced no usable value yet.

For tokens, use NZ; for function results, fallback the inputs or warm-up gate the rule.

EXPR_FUNCTION_INPUT_NA

Warn

A function received NaN input.

Use NZ on the missing input before the function call.

EXPR_PERCENT_BASE_INVALID

Warn

A percent-from base value was zero or NaN.

Use SAFE_DIV or provide a non-zero fallback base.

EXPR_PERCENT_PREVIOUS_INVALID

Warn

A percent-change previous value was zero or NaN.

Use SAFE_DIV, NZ, or a fallback previous value.

EXPR_LENGTH_INVALID

Warn

A function length was invalid or unavailable.

Use positive whole-number lengths.

EXPR_DOMAIN_INVALID

Warn

A math function received a value outside its domain.

Clamp or validate the input first.

EXPR_ROUND_STEP_INVALID

Warn

ROUND_STEP received an invalid step.

Use a positive non-zero step.

EXPR_CLAMP_RANGE_INVALID

Error

CLAMP received an invalid range.

Make sure min is less than or equal to max.

Example: wrong final type

Boolean fields need a boolean result:

entry_trigger_when:
  PRICE_CLOSE

Repair it by using a comparison:

entry_trigger_when:
  PRICE_CLOSE > EMA_20

Numeric fields need a number:

entry_limit_price:
  CROSS_OVER(PRICE_CLOSE, EMA_20)

Repair it by returning a price:

entry_limit_price:
  PRICE_CLOSE * 0.995

Example: unsupported namespace

Strategy Lab expressions use parser aliases, not raw Pine namespaces:

setup_active_when:
  ta.sma(close, 20) > ta.sma(close, 50)

For unsupported indicator calculations such as SMA, EMA, RSI, MACD, or ATR, calculate the value in an indicator and connect it as a custom token:

setup_active_when:
  SMA_20 > SMA_50

Token Codes

Token diagnostics usually mean the engine could not safely resolve a built-in token, custom token, or generated state token.

Code

Severity

What happened

Usual fix

TOKEN_COLLISION

Warn

Two custom token names collide after sanitization.

Rename one custom token.

TOKEN_UNKNOWN

Error

A token was referenced but not found.

Check spelling, custom token assignment, and generated state-token names.

Custom token names and YAML unit names become state tokens after sanitization. Keep names clear and unique:

- entry_name: PULLBACK_ENTRY

can create state tokens such as:

PULLBACK_ENTRY_WORKING
PULLBACK_ENTRY_ACTIVE

If two names sanitize to the same base, rename one of them.

YAML unit-name collisions that would create duplicate state tokens are reported as YAML_DUPLICATE_NAME, not TOKEN_COLLISION.


Strategy and Runtime Codes

These diagnostics come from the Strategy Lab layer after YAML and expression parsing.

Code

Severity

What happened

Usual fix

STRATEGY_CONSENT_REQUIRED

Error

Required user consent or safety acknowledgement is not enabled.

Review settings and enable the confirmation when intentional.

STRATEGY_RUNTIME_NOT_READY

Error

The engine does not have enough valid configuration to run.

Fix earlier YAML or expression diagnostics first.

STRATEGY_SETUP_LINK_MISSING

Error

A unit points at a setup that does not exist.

Fix *_belongs_to_setup or add the setup.

STRATEGY_ORDER_SKIPPED

Warn

An order could not be submitted in the current runtime state.

Check position state, remaining size, order type, and trigger conditions.


Diagnostic Engine Codes

These diagnostics are about the diagnostic system itself.

Code

Severity

What happened

Usual fix

DIAG_REPORT_CAPACITY_REACHED

Warn

The retained diagnostics list filled up.

Fix the first visible issues, then reload to reveal the next set.

DIAG_UNKNOWN_CODE

Error

A diagnostic code was emitted without a known registry entry.

Treat as a bug-report candidate and include the code, field, and expression.


Repair Patterns

Use NZ when a missing value should become a fallback value:

entry_trigger_when:
  PRICE_CLOSE > NZ(EMA_50, PRICE_CLOSE)

Use NZ on a historical lookup when the lookup may not exist yet:

entry_trigger_when:
  PRICE_CLOSE > NZ(PRICE_CLOSE[5], PRICE_CLOSE)

Use SAFE_DIV when a denominator can be zero or missing:

entry_trigger_when:
  SAFE_DIV(PRICE_CLOSE - NZ(PRICE_CLOSE[5], PRICE_CLOSE), NZ(PRICE_CLOSE[5], PRICE_CLOSE), 0) > 0.01

Use a warm-up gate when a rule should stay quiet until the chart has enough bars:

setup_active_when:
  BAR_INDEX > 200
  && PRICE_CLOSE > EMA_200

Use state tokens when one unit should depend on another unit being working or active:

take_profit_gate_condition:
  POSITION_ACTIVE
  && PULLBACK_ENTRY_ACTIVE

Use position tokens when exits should depend on the current overall position:

stop_loss_gate_condition:
  POSITION_ACTIVE
  && POSITION_REMAINING_PERCENT <= 50

The point is not to silence every warning. The point is to make your intent explicit enough that the engine can test the trade you meant, not whatever an early chart bar, missing token, or invalid denominator happened to produce.

Was this helpful?

Still need help? Ask the team