ChartnautDocs

Lint and error codes

Every lint rule id and runtime error code Chartnaut reports for scripts, with its severity and the fix. Look up the id shown in the builder's Problems list or in an agent's tool result, fix the line, and lint again.

How to read this page

  • error blocks the save, the preview or the run. warn is advisory: the script runs, but the result is worse or will surprise someone.

  • Where says which script type the rule checks: I indicator, D definition, S study. Some rules have a different severity per type; the table says so.

  • The indicator lint runs in the builder and in the agents' lint_indicator tool, so a person and an agent see the same findings. A definition is linted by the same rule set on save and by the Definition authoring agent.

  • A few problems throw without a rule id. The common ones are listed in the last section of this page.

Sandbox

Id

Severity

Where

Fix

caps/forbidden-dsl

error

D

Remove the blocked call: document.*, window.*, eval(), new Function(), phenomena.find(), ICT.*, composition.*, or an inline function inside dialog({ settingsValidator }) (use validatorId).

caps/no-async

error

D, S

Scripts are synchronous. Remove await, async function, setTimeout, setInterval, requestAnimationFrame, queueMicrotask and new Promise.

caps/no-network

error

D, S

Remove fetch, XMLHttpRequest, WebSocket and navigator.sendBeacon. Read data through declared dependencies.

caps/non-deterministic

error

D, S

Replace Date.now(), new Date(), performance.now() and crypto.randomUUID with the bar's own time (ctx.time, or the event time in a study).

caps/no-imports

error

D

Replace require() with a relative ESM import from another file in the same definition.

caps/unbounded-loop

warn

I

while (true) or for (;;) needs an explicit break. Prefer a bounded loop.

Files, modules and entry

Id

Severity

Where

Fix

bundle/no-files

error

D, S

Add a file.

bundle/no-entry

error

D

Mark one file as the entry (role: "main") and check its path.

bundle/multiple-main

error

D

Keep exactly one role: "main" file.

bundle/no-entry-meta

error

D, S

Put meta({...}) in the entry file.

bundle/duplicate-path

error

D

Two files share a path. Rename one.

bundle/multi-file

error

S

Studies are one file. Merge helpers into study.js.

bundle/no-on-event

error

S

Declare export function onEvent(ctx, scope). Without it the run produces no rows or results.

bundle/scope-duplicate

error

S

The study exports scope() more than once. Export it once.

bundle/scope-and-scope-event

error

S

The study exports scope() and also calls ctx.scopeEvent(). scope() returns the event's scope tuple, so remove the ctx.scopeEvent call.

bundle/scope-in-trade-study

error

S

Trade studies group by trade and never export scope(). Group trades in onPosition and onFinish.

bundle/empty

error

S

The study bundled to nothing. Check the file has code.

meta/entry-only

error

D

Move meta() into the entry file.

runtime/onbar-required

error

D

The entry file must declare export function onBar(ctx).

runtime/onbar-entry-only

error

D

Only the entry file exports onBar. Export helpers as plain functions and call them from it.

runtime/onbar-multiple

error

D

More than one file exports onBar. Keep the entry's.

runtime/no-onbar

warn

D

No file exports onBar, so the preview runs and emits nothing.

modules/bare-import

error

D

Package imports are not supported. Use a relative path such as ./levels.js.

modules/missing-extension

error

D

Write the extension: ./levels.js, not ./levels.

modules/cjs-extension

error

D

.cjs files are not supported. Use .js or .mjs.

modules/path-escape

error

D

The path leaves the definition's folder. Keep imports inside it.

modules/unresolved-import

error

D

The imported file does not exist. Fix the path or add the file.

modules/import-cycle

error

D

Two files import each other. Move the shared code into a third file.

modules/parse-error

error

D

Syntax error in a module. The message names the file and position.

modules/unsupported-export

error

D

Export with export const or export function. Default exports and live bindings are not supported.

modules/top-level-await

error

D

Remove await at module scope.

modules/dynamic-import

error

D

Replace import() with a static relative import.

modules/unreachable-file

warn

D

Nothing imports this file from the entry, so it never runs. Import it or delete it.

derive/no-meta

error

D, S

Add a meta({...}) call.

derive/multiple-meta

error

D, S

Keep one meta({...}). Only the first is used.

derive/eval

error

D, S

The script threw while its declarations were read. The message is the thrown error.

derive/compile

error

D, S

The script did not compile. Fix the syntax error in the message.

derive/settings-dialog

error

D, S

The settings declarations are invalid. The message names the input.

derive/flows-missing

error

S

flows.declare(...) is in the source but no flow was derived. Usually a syntax error above it.

derive/timeframes

error

D

Saving could not work out the definition's timeframes. Fix the tf/* errors first.

derive/deps

error

D

A declared dependency cannot be read by your account. Pick one you own or one that is public.

settings/dialog-required

error

D

The definition declares inputs but no dialog(...), so the inputs reach nothing. Add dialog({ title }).

Meta, settings and data source

Id

Severity

Where

Fix

meta/missing-name

warn

D

Give meta({ name }) or shortName.

meta/kind-mismatch

error

D

meta({ kind }) must match the definition's kind. Use kind: "flow".

meta/window-is-run-window

warn

D

meta({ window }) describes which bars to compute over. That option is runWindow; window takes { on }.

meta/timeframe-deprecated

warn

D

Replace window: { timeframe } with timeframe handles.

meta/timeframes-deprecated

warn

D

Drop window: { timeframes }. Timeframes are inferred from timeframe(...) handles.

meta/timeframes-empty

error

D

The legacy timeframes list is empty. Remove it.

meta/timeframes-unknown

error

D

The legacy timeframes list has an unknown timeframe. Remove it.

meta/timeframes-not-multiples

warn

D

A higher timeframe is not a whole multiple of the lowest. Buckets will misalign.

meta/run-on-empty

error on I, warn on D

I, D

runOn: [] allows nothing. Omit runOn or list at least one timeframe.

meta/run-on-unknown-tf

error

I, D

runOn lists a timeframe Chartnaut does not know. Use 1m, 5m, 15m, 30m, 1h, 2h, 4h, 1d or 1w.

meta/data-source-invalid

error

I, D

dataSource.type must be "candles" or "volume-candles"; purgeStrategy must be "floor-aware", "max-bars" or "session-daily".

meta/volume-candles-purge-required

error

I, D

dataSource: { type: "volume-candles" } needs settings: { purgeStrategy: "floor-aware" }. The string form dataSource: "volume_candles" needs no settings.

runtime/price-levels-without-volume-datasource

warn

I, D

ctx.volumePriceLevels needs meta({ dataSource: { type: "volume-candles", ... } }). Without it the tape is always [].

params/unknown-type

error

D, S

Use a known param type: number, string, boolean, color, timeframe, multiSelect, range or array. colour is spelled color.

params/color-default-invalid

error

D, S

The color default is not a valid color.

params/color-alpha-disallowed

error

D, S

The default has alpha but the param does not set allowAlpha.

params/string-looks-like-color

warn

D, S

A string param has a color default. Use type: "color" to get a picker.

outputs/color-from-undeclared

error

D

colorFrom names a setting that meta.params does not declare.

outputs/color-from-not-color

error, or warn for a string param

D

colorFrom must name a color param.

settings-validator/unknown-id

warn

I

dialog({ settingsValidator: { validatorId } }) names no registered validator. The message lists the known ids.

settings-validator/unknown-gate

warn

I

Use a known gate: instrument, timeframe, chartType, assetClass, priceRange or trigger.

Timeframes and summaries

Id

Severity

Where

Fix

tf/security-removed

error

I, D

ctx.security(...) and ctx.tf(...) in onBar were removed. Declare const h = timeframe("1d") at module scope and read h.last, h.forming, h.bars(n) or h.state. The message carries the rewrite.

tf/handle-not-module-scope

error

I, D

Call timeframe(...) and .onBar(...) at module scope, next to your inputs, not inside a function.

tf/no-ctx-at-module-scope

error

I, D

Pass the input.timeframe handle itself to timeframe(), not ctx.params.<id>.

tf/missing-source

error

I, D

timeframe(...) needs a literal ("1d"), "chart", or an input.timeframe handle.

tf/untyped-source

error

I, D

The argument is not timeframe-typed (a template string, a free variable). Use a literal, "chart" or an input.timeframe handle.

tf/use-input-timeframe

warn on I, error on D

I, D

An input.select whose options are all timeframes. Use input.timeframe({ id, label, default, options }).

tf/invalid-input-timeframe

error

I, D

input.timeframe(...) needs an object literal with literal id and default.

tf/unknown-option

error

I, D

The only option is reads: timeframe(tf, { reads: [handle] }).

tf/reads-not-a-handle

error

I, D

reads must be an array literal of handles declared above this one.

tf/reads-forward-reference

error

I, D

reads names a handle declared below. Reorder, or split the state into a third handle.

tf/undeclared-read

error

I, D

Inside a handler, ctx.tf(x) must pass a handle object that is listed in that handle's reads.

tf/duplicate-handler

error

I, D

One onBar per handle. Merge the two handlers.

tf/parse-error

error

I, D

The timeframe analyser could not parse the source. Fix the syntax error first.

timeframe/no-output-in-handler

error

I, D

ctx.plot, emit, hline, range or mark inside a timeframe handler. Keep the value with ctx.accum and paint from the chart onBar. Also raised at run time.

timeframe/undeclared-read

error

I, D

Run-time form of tf/undeclared-read.

timeframe/unknown-option

error

I, D

Run-time form of tf/unknown-option.

timeframe/reads-not-a-handle

error

I, D

Run-time form of tf/reads-not-a-handle.

timeframe/reads-unused

warn

I

A handle lists a read its handler never calls. Drop it or read it.

flow/unknown-timeframe

error

D

timeframe("X") where X is not a known timeframe or "chart".

summary/missing-window

error

I, D

ctx.summary(tf) needs a window, e.g. { since: "52w" }.

summary/untyped-window

error

I, D

Write the window as an object literal, not a variable or spread. The runtime sizes history from it.

summary/invalid-window

error

I, D

Keys are { since } or { period, back }. since is "all", a duration, a date or a period name; back is a whole number of zero or more.

History window and state

Id

Severity

Where

Fix

window/warmup-required

error

I, D

The script keeps state but declares no warmup, so its values would depend on where the run began. Call warmup(...) after your inputs: w.window(length) for a lookback, w.ema(length) or w.wilder(length) for smoothing, w.day() or w.span("7d") for state that resets on a session or calendar boundary, w.forever() for state that never forgets (a sum, a count, an all-time high).

window/warmup-inert

error

I, D

A warmup is declared and handles exist, but no handle registers an onBar handler, so nothing walks it.

window/declare-with-call

error

D

A warmup or retain key inside meta({ window }). window takes { on }. Declare history with the warmup(...) or retain(...) call the message names, after your inputs.

state/never-forgets

error on I, warn on D

I, D

A running sum, count or high declared with a count means "since the cell began". Declare warmup((w) => w.forever()), or reset it on a boundary and declare the span between resets, such as w.day().

window/forever-on-decaying

warn

I, D

w.forever() on state that only decays fetches the whole cap for nothing. Declare w.ema(length) or w.wilder(length).

window/reset-wants-span

warn

I, D

The script resets on ctx.session.isStart but declares a typed count, which is a different stretch of time on every timeframe. Declare w.day(), or w.span("7d") for a weekly reset.

window/decay-under-factor

warn

I, D

An EMA or Wilder average whose length the lint can read is declared under 30x (EMA) or 50x (Wilder) that length. Declare w.ema(length) or w.wilder(length).

window/clamped-to-cap

warn

I, D

The declared warmup or retain exceeds your plan's indicator memory on a timeframe and was clamped. The message gives the effective warmup and retain. Read a higher timeframe or use ctx.summary for a longer span.

The state/never-forgets warning on definitions will become an error once the number of existing definitions it would refuse has been measured.

Events and emits

Id

Severity

Where

Fix

events/missing-id

error

D

Give events.declare an id.

events/missing-intent

error

D

Give events.declare an intent, e.g. "signal".

events/duplicate-id

error

D

An event id is declared twice across files.

events/bad-payload-type

error

D

A payload field type must be string, number, boolean, object, array or { enum: [...] }.

events/payload-missing-description

error

D

Every payload field needs { type, description }. Study agents read the description.

events/reserved-payload-key

error

D

Remove _displayLabel or _displaySubtitle from the payload and pass label and subtitle in the ctx.emit options. Remove _firedBarTime: Chartnaut records the bar each event fired on under that key.

events/unknown-paint

warn

D

Use none, pin, highlight_event_bar, highlight_price or highlight_event_bar_and_price.

events/hidden-paint-explicit

warn

D

paint: "none" hides every emit on the chart. Use "pin" unless you want data-only events.

events/paint-needs-price

warn

D

Price paints need a numeric payload.price or ctx.emit(..., { price }).

events/emit-missing-label

warn

D

Pass a non-empty label in the ctx.emit options. At run time an emit without a label is dropped.

marker/duplicate-paint

warn

D

The same event is painted by ctx.emit and ctx.mark. Keep one channel.

snapshot/schema-mismatch

error

D

A snapshot schema field has an invalid type.

snapshots/duplicate-id

error

D

A snapshot id is declared twice.

Outputs and lifecycle

Definitions use outputs.declare and the outputs/* rules. Indicators use output.* and the output/* rules.

Id

Severity

Where

Fix

outputs/unknown-id

error

D

ctx.<verb>("id") names an output that outputs.declare does not declare.

outputs/kind-mismatch

error

D

The paint verb does not match the declared kind, e.g. ctx.hline on a line output.

outputs/declared-unused

warn

D

An output is declared but never painted.

outputs/hline-missing-time1

error

D

ctx.hline(id, price, { time1 }) needs an anchor time: time1: ctx.time, or the event's anchor time.

outputs/invalidate-needs-time1

error

D

Invalidating hlines need time1 on every emission.

outputs/all-needs-distinct-time1

warn

D

mode: "all" with a literal time1 collapses every emission onto one anchor. Use a per-bar time.

outputs/invalid-mode

error

D

mode applies to hline, range and trendline only, and must be one that kind allows.

outputs/missing-mode

warn

D

Set mode explicitly on hline, range and trendline.

outputs/invalidate-needs-policy

error

D

mode: "invalidateOnCustomFunction" needs invalidateWhen. There is no default.

outputs/invalidate-without-mode

warn

D

invalidateWhen is ignored unless mode is "invalidateOnCustomFunction".

outputs/unknown-invalidate-preset

warn

D

The preset name is not known for this kind. Use a listed preset or a predicate function.

outputs/trendline-no-presets

error

D

Trendlines take a predicate function, never a preset name.

outputs/event-needs-binding

error

D

mode: "invalidateOnEvent" needs invalidateOnEvent: "<event id>".

outputs/event-without-mode

warn

D

invalidateOnEvent is ignored unless mode is "invalidateOnEvent".

outputs/unknown-event-binding

error

D

invalidateOnEvent names an event that events.declare does not declare.

outputs/label-mode-invalid

error

D

labelMode is always, onHover, onLastBar or none.

outputs/zindex-not-finite

error

D

zIndex must be a finite number.

outputs/note-missing-price

error

D

ctx.note needs a numeric price.

outputs/mark-missing-text

warn

D

Pass text to ctx.mark when labelMode is always or onHover.

outputs/range-missing-label

warn

D

Pass label to ctx.range when labelMode is always.

outputs/trendline-missing-coords

error

D

ctx.trendline needs time1, price1, time2 and price2.

output/range-invalidate-needs-policy

error

I

Same as outputs/invalidate-needs-policy, for output.range.

output/range-invalidate-without-mode

warn

I

Same as outputs/invalidate-without-mode, for output.range.

output/range-unknown-preset

warn

I

Unknown invalidateWhen preset on output.range.

output/hline-invalidate-needs-policy

error

I

Same, for output.hline.

output/hline-invalidate-without-mode

warn

I

Same, for output.hline.

output/hline-unknown-preset

warn

I

Unknown invalidateWhen preset on output.hline.

output/hline-event-without-mode

error

I

invalidateOnEvent on output.hline is ignored unless mode is "invalidateOnEvent".

output/trendline-invalidate-needs-policy

error

I

output.trendline with invalidateOnCustomFunction needs a predicate.

output/trendline-invalidate-without-mode

error

I

invalidateWhen on output.trendline is ignored without the mode.

output/trendline-preset-unsupported

error

I

Trendlines have no presets. Pass an inline predicate.

output/trendline-event-without-mode

error

I

invalidateOnEvent on output.trendline is ignored without the mode.

output/expires-required

error

I

An invalidating output needs expires, e.g. expires: "5d", or "max" for no expiry.

output/expires-without-mode

warn

I

expires has no effect unless mode is "invalidateOnCustomFunction" or "invalidateOnEvent".

output/invalidate-per-emit-fn

error

I

invalidateWhen: fn on a ctx.hline, ctx.range or ctx.trendline emission cannot be re-checked past the cell that emitted it. Declare the rule on the output and pass per-level numbers through meta.

output/invalidate-predicate-shape

error

I, D

The predicate reads the wrong shape. It receives { bar, entry, history }, e.g. ({ bar, entry }) => bar.low <= entry.top && bar.high >= entry.bottom.

output/invalidate-predicate-ctx-name

warn

I, D

Rename the predicate argument from ctx. Destructure ({ bar, entry, history }).

On indicators, only the rules the builder classes as advisory are warnings. The trendline and hline-event-without-mode rules are not on that list, so they block.

Layers

Id

Severity

Where

Fix

layer/no-write-in-renderer

error

I, D

No upsert, patch, seal, remove or ctx inside layout, paint, paintGL, hit, autoscale or legend. Write rows from onBar, onRun or a gesture.

layer/no-write-in-timeframe-handler

error

I, D

Write layer rows from the chart onBar, not inside a timeframe(...) handler.

layer/upsert-never-called

error

I, D

Nothing writes to the layer. Call upsert() or patch() from onBar or onRun, or add a gesture.

layer/expires-required

error

I

A layer that seals rows (sealWhen or sealOn) needs expires.

layer/rows-in-bar-hook

warn

I, D

.rows() in onBar scans every row on every bar. Use get(key), last() or range(t1, t2).

layer/renderer-not-registered

warn

I, D

The layer has neither paint nor paintGL, so nothing draws. Fine for a data-only layer.

layer/escape-hatch

warn

I, D

p.all(), p.bitmap, g.raw or g.program bypasses culling. Budget it.

outputs/layer-use-output-layer

warn

I, D

outputs.declare({ kind: "layer" }) returns no handle. Use const rows = output.layer({ id, row, derived }).

Dependencies

Id

Severity

Where

Fix

indicators/missing-slug

error

D

indicators.declare needs slug.

indicators/missing-as

error

D

indicators.declare needs as, the local alias.

indicators/duplicate-as

error

D

Each as must be unique.

indicators/legacy-shape

error

D

Replace { id, symbol, args } with { slug, as, version, settings } and read ctx.indicators.<as>.

indicators/missing-version

error

D, S

Pin version (a positive integer; natives use 1).

indicators/unknown-slug

error

D

No native, scripted indicator or definition has this slug.

indicators/version-not-found

error

D

The pinned version does not exist. The message lists the ones that do.

indicators/cycle

error

D

The dependency graph loops back to this script.

indicators/container-series-read

error

D

Read series by output key: ctx.indicators.<as>.<outputKey>.value, never ctx.indicators.<as>.value. The message lists the keys.

flows/missing-version

error

S

Pin version on flows.declare.

study/indicator-missing-version

warn

S

Server form of the same check: an unpinned indicator floats to the latest version.

study/flow-missing-version

warn

S

Server form: an unpinned definition floats to the latest version.

imports/missing-flow-id

error

D

imports.use needs flowId.

imports/missing-alias

error

D

imports.use needs alias.

imports/duplicate-alias

error

D

Each import alias must be unique.

flow/upstream-lifecycle-reimplementation

error

D

The definition rebuilds zone invalidation that its dependency already has. Read ctx.indicators.<as>.lifecycle() instead.

indicator/native-version-mismatch

error at run time

D, S

A built-in indicator was pinned to a version other than 1.

Sessions and ctx use

Id

Severity

Where

Fix

flow/session-legacy-api

error

D

ctx.session.window, boundsOf and isStart are not available. Use ctx.session({ period, open?, close?, tz? }) and s.didOpen, s.didClose, s.isOpen, s.prev.

flow/session-bar-count-gate

error

D

ctx.session takes no length or tf. Sessions end by clock: gate on s.didClose.

flow/session-bucket-param

warn

D

A param looks like a bar-count session knob. Use ctx.session instead.

flow/hand-rolled-session-counter

warn

D

Math.floor(t / 86400) day rollover. Use ctx.session.

flow/ctx-fn-as-value

error

D

ctx.accum, ctx.plot and the other ctx functions must be called, not stored. A stored function cannot cross to the chart.

Workload

Id

Severity

Where

Fix

workload/fine-price-step

warn

I

A loop steps price by 0.01 or finer. On BTC that is tens of thousands of iterations per bar. Use the instrument tick size or a row-size setting.

workload/price-step-soft, workload/price-step-hard

warn in the dry run

I, D

The projected rows per bar are high (soft) or excessive (hard). Coarsen the row size.

workload/tpo-zone-size-soft, workload/tpo-zone-size-hard

warn in the dry run

I, D

The TPO zone spans too many ticks. Check the tick size.

Studies

Id

Severity

Fix

study/no-emit

error

ctx.emit is definition-only. Use ctx.collect and ctx.publish.

study/no-snapshot

error

ctx.snapshot is not available in studies.

study/no-accum

error

ctx.accum is not available. Use ctx.collected(...) in onEvent for earlier events.

study/no-timeframe-handles

error

timeframe(...) is not available. Read declared definitions and indicators.

study/no-priceLevels

error

The volume-at-price tape is not available. Read upstream events, visuals or lifecycle().

study/no-events-declare, study/no-snapshots-declare, study/no-output, study/no-outputs-declare, study/no-imports

error

Definition-only DSL. Studies use flows.declare, results.declare and ctx.publish.

study/forward-bad-opts

error

ctx.candles.forward() takes minutes, bars, untilTime, stopAt, targetAt, firstHit and atBar.

study/window-as-object

error

ctx.candles.window() returns a flat array. Iterate it; there is no .bars or .candles.

study/window-absolute-time

warn

before and after are seconds relative to the event time, not timestamps.

study/session-boundsof-arity

error

ctx.session.boundsOf(t) gives the UTC day only. Use ctx.temporal.containing(t, { period }).

study/session-key-not-numeric

error

ctx.session.key(t) is a YYYY-MM-DD string. Use ctx.temporal.containing(t, { period: "day" }).start for day arithmetic.

study/ctx-out-of-scope

error

ctx used in a helper that does not receive it, or at module scope. Pass ctx as a parameter.

study/event-flow-branch-mismatch

error

ctx.event.flow is compared to a name that is not a flows.declare({ as }) alias.

study/payload-key-undeclared

error

ctx.event.payload.<key> is not in any declared definition's payload.

study/payload-shape-mismatch

warn

A published payload is missing keys its result kind needs.

study/unsafe-multi-output-indicator-access

error, or warn for an unguarded read

Read ctx.indicators.<as>.<outputKey>?.valueAt(t) and guard with Number.isFinite.

study/ranges-not-lifecycle

error

Do not treat ranges() fields such as closedAt as lifecycle. Use .lifecycle().

study/lifecycle-source-missing

error

Survival or invalidation measurements need .lifecycle() or a secondary event join events({ after, filter }).

study/publish-only-in-onFinish

error

Call ctx.publish only in onFinish.

study/collect-not-in-onFinish

error

ctx.collect writes are not allowed in onFinish. Read with ctx.collected().

study/no-event-cursor-in-onFinish

error

Event-cursor APIs have no clock in onFinish and return empty. Measure in onEvent and collect the result.

study/publish-without-declare

error

Add results.declare({ id, kind, title }) for the published id.

study/declare-without-publish

warn

A declared result is never published.

study/result-missing-description

warn

Add a description to the result. Forward Insight popovers show it.

study/missing-answer-prose

warn

Add a kind: "prose" result published with role: "answer".

study/readout-missing

warn

Heavy chart results need a compact readout__* metric.

study/publish-looks-indexed

warn

Rows carry a dimension but the result has no indexedBy.

study/publish-missing-index-column

error

Rows (or popover_layout cells) must include every indexedBy column.

study/publish-missing-declared-column

warn

A declared column is not set on published rows.

study/dimension-declare-fields

error

dimensions.declare needs id, title and description.

study/dimension-invalid-role

error

role is "scope" or "report".

study/dimension-id-unique

error

A dimension id is declared twice.

study/scope-required

error, or warn on a hand edit of a study that groups with ctx.scopeEvent

Export scope(ctx): it returns each event's scope tuple from what was known when the event fired, or null to leave the event out. It is an error when the study groups nothing, for a new study, and for every agent edit.

study/scope-return-keys

error

scope() returns a key that is not a declared dimension, or does not return every scope dimension on every path. A tuple built at run time is checked when the study runs.

study/scope-report-dimension

error

scope() returns a role: "report" dimension. Measure the outcome in onEvent, collect it and publish it through indexedBy.

study/scope-no-return

error

scope() never returns, or has a bare return;. Return the tuple, or null to leave the event out.

study/scope-forward-read

error for ctx.candles.forward, warn for events({ after })

scope() sees only what was known when the event fired. Read forward bars and later events in onEvent.

study/scope-side-effect

error

scope() calls something that is not available there: ctx.collect, ctx.collected, ctx.state, ctx.rand, ctx.cluster, ctx.scopeEvent, ctx.publish, ctx.popoverLayout, ctx.plot, ctx.range, ctx.mark, ctx.hline, ctx.note, ctx.groupByScope, ctx.emit or ctx.snapshot. Measure and record in onEvent; use ctx.previous() for earlier events.

study/scope-reads-module-state

error

scope() reads a module variable that other events change. The chart groups one event on its own and would not see it. Derive the group from the event, its past data or ctx.previous().

study/record-only-in-onEvent

error

A study without scope() calls ctx.scopeEvent outside onEvent. Move the grouping into scope(ctx).

study/record-multiple

warn

A study without scope() calls ctx.scopeEvent more than once in onEvent. Export scope(ctx) returning one tuple.

study/record-unknown-dimension

error

A study without scope() passes an undeclared dimension to ctx.scopeEvent.

study/record-report-dimension

error

A study without scope() passes a role: "report" dimension to ctx.scopeEvent. It belongs in indexedBy.

study/record-missing-declared-dimension

error

A study without scope() collects rows but its ctx.scopeEvent never sets a declared scope dimension.

study/record-non-canonical-dimension-value

error

A scope value is not one of the dimension's declared values. Display labels go in blocks.

study/record-without-publish

warn

A scope dimension is in no result's indexedBy.

study/report-dimension-unused

warn

A report dimension is in no result's indexedBy.

study/joint-cell-required

warn

The scope tuple holds two or more scope dimensions, so publish one result indexed by all of them.

study/bucket-record-without-bucketed-publish

warn

A study without scope() calls ctx.scopeEvent({ bucket }) with no bucketed result. Declare dimensions and return them from scope().

study/bucketed-publish-without-bucket-record

warn

Bucketed results need declared dimensions returned from scope() for Forward Insights to match.

study/dry-run

error

The Study authoring agent's proposal failed a real run on a preset market. The faults are listed.

Run-time errors

Indicator and definition budgets

A script that goes over a budget stops with <kind> exceeded: <observed> / <limit> and a remedy. Soft limits warn once; hard limits stop the run.

Kind

Limit

Fix

run_wall_clock

warn at 2 s, stop at 30 s per calculation

Use less history or do less per bar.

handler_wall_clock

5 s in one handler call

Avoid loops over every price tick on every bar.

loop_iterations

350,000 per handler; per run it scales with bars, from 2 million to 50 million

Process each higher-timeframe bucket once; use the tick size.

ctx_calls

500,000 per handler

Fewer ctx.plot, emit, range and accum calls per bar.

indicator_points

warn at 500,000, stop at 2,000,000

Emit on transitions only, or use less history.

emitted_events

warn at 25,000, stop at 100,000

Tighten emit conditions or declare oncePer.

accum_slots

warn at 256, stop at 1,024

Reuse fewer ctx.accum ids.

lifecycle_instances

warn at 2,500, stop at 10,000

Emit fewer persistent ranges, or use mode: "replace".

collected_rows

100,000 per key, 500,000 total

Aggregate before collecting.

payload_size

Publish smaller payloads.

layer_rows

warn at 5,000, stop at 20,000 rows per layer

Seal and remove old rows, or key one row per session.

layer_bytes

warn at 4 MB, stop at 32 MB per layer

Coarsen bins or grid steps, or remove old rows.

warmup_replay

warn at 2.5 s, stop at 10 s

Lower the warmup, or keep running sums in handlers instead of arrays.

Layers also stop with frame hooks are read-only when a renderer writes, and pause with paint exceeded the 4 ms frame budget when painting stays slow for three frames.

Emits dropped at run time

A definition's run counts every emit it drops. These are the reasons:

Reason

Cause

Fix

missing_label

ctx.emit without label.

Pass { label }.

unknown_event_id

The id has no events.declare.

Declare it.

dedupe_oncePer

The event's oncePer keys matched an earlier emit.

Expected. Widen the keys if you wanted repeats.

warmup

The bar was in the warmup. Warmup bars compute state but record no events.

Expected.

Dependency output

Code

Cause

Fix

dependency_output_unavailable

A declared dependency produced no value for the output you read.

See Dependency unavailable.

Study run errors

A failed study run reports one of these kinds with a request ID for support.

Kind

Meaning

Fix

compile_error

The study did not compile.

Fix the error in the message.

runtime_error

The study threw.

Fix the line in the message.

script_execution_timeout

One event took longer than 15 s, or onFinish or startup took too long.

Do less per event.

too_many_event_timeouts

10 or more events timed out in one run.

Do less per event.

too_many_event_errors

Events kept throwing.

Fix the first reported error.

budget_wall_clock

The run passed 10 minutes.

Use a shorter range or fewer dependencies.

memory_limit

The run ran out of memory.

Use a shorter range.

budget_call_stack

Recursion deeper than 1,024 calls.

Remove the recursion.

budget_total_events

More than 100,000 events.

Use a shorter range or a more selective definition.

budget_emitted_events

The definition produced too many events.

Tighten its conditions.

budget_indicator_points

An indicator produced too many points.

Use a shorter range or fewer outputs.

budget_collected_rows

Too many collected rows.

Collect fewer values.

budget_annotations

More than 10,000 chart annotations.

Annotate less often.

budget_payload

Results too large.

Publish fewer or smaller results.

budget_forward_bars

A forward scan of more than 5,000 bars.

Shorten the forward window.

budget_kmeans_iterations, budget_bootstrap_samples, budget_pca_features

Statistics helper limits: 200 iterations, 100,000 samples, 128 features.

Reduce the size.

data_query_timeout

Market data did not load in time.

Try again.

dependency_failed

A definition run the study waited on did not finish.

Retry the definition run.

unsupported_data_type

The instrument cannot serve data the study needs, such as the volume tape on an FX CFD.

Pick another instrument.

security_policy_violation

The script generates code at run time.

Remove eval or Function.

capacity_unavailable

Study execution is busy.

Try again shortly.

cancelled

The run was cancelled.

internal

Something failed on Chartnaut's side.

Contact support with the request ID.

Scope errors

A problem with one event's scope() call leaves that event out of the study and the run continues. The run lists each error.

Message

Fix

scope() returned undefined: return the event's scope tuple, or null to leave the event out of the study

Return on every path.

scope() returned <value>: return an object of scope dimensions, or null

Return an object.

scope() returned "<key>", which is not a declared dimension

Declare it, or drop it from the tuple.

scope() returned "<key>", a report dimension (role: "report")

Measure it in onEvent and publish it through indexedBy.

scope() did not return "<key>": every scope dimension needs a value for every event in the study

Set every scope dimension in every tuple.

scope() returned "<key>": <reason>

The value is outside the dimension's declared values. Use a canonical value.

scope threw: <error>

Fix the line in the error.

ctx.candles.window({ after }) reads <time>, after the event fired (<time>): ...

scope() read past the bar the event fired on. Read later data in onEvent.

A finished run warns with study/pin-cell-count-mismatch when a pin_cell reports an n that differs from the number of events scope() put in that group. Build cells from ctx.groupByScope(rows) so each n counts exactly the events a marker can land in. See scope.

Errors without a rule id

Message starts with

Where

Fix

meta(...) is required

I

Add meta({ shortName, kind }) at the top.

dialog(...) is required

I

Add dialog({ title }). Indicators always need one.

output.<kind>: 'id' is required

I

Give every output an id.

meta({ mode: "once" }) requires an exported onRun(ctx)

I

Export onRun, or drop mode: "once".

onRun(ctx) requires meta({ mode: "once" })

I

Add mode: "once", or rename onRun to onBar.

meta: window takes { on }

I

A warmup or retain key inside meta({ window }). Declare it with its own warmup(...) or retain(...) call after your inputs.

window.<key> is not an option

I

window takes { on }. Use runWindow for the bars a mode: "once" script computes over.