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 2 days 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:

Example
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:

Example
Long Entries > PULLBACK_ENTRY > Entry Trigger

means:

Example
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:

Example
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:

Example
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:

Example
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:

Example
entry_trigger_when: PRICE_CLOSE > PRICE_CLOSE[5]

Use NZ on the lookback value:

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

Or gate the rule until the lookback can exist:

Example
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:

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

Put the safety inside the calculation:

Example
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

Example
- 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

Example
- 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:

Example
entry_trigger_when: PRICE_CLOSE

Repair it by using a comparison:

Example
entry_trigger_when: PRICE_CLOSE > EMA_20

Numeric fields need a number:

Example
entry_limit_price: CROSS_OVER(PRICE_CLOSE, EMA_20)

Repair it by returning a price:

Example
entry_limit_price: PRICE_CLOSE * 0.995

Example: unsupported namespace

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

Example
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:

Example
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:

Example
- entry_name: PULLBACK_ENTRY

can create state tokens such as:

Example
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:

Example
entry_trigger_when: PRICE_CLOSE > NZ(EMA_50, PRICE_CLOSE)

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

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

Use SAFE_DIV when a denominator can be zero or missing:

Example
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:

Example
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:

Example
take_profit_gate_condition: POSITION_ACTIVE && PULLBACK_ENTRY_ACTIVE

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

Example
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.