Skip to main content

Troubleshooting

Start with the visible symptom, then inspect the lowest public boundary that could explain it. Debug logging proves which widget, adapter, or runtime path fired. It does not replace a reproducible test.

Turn on bounded diagnostics

sdk.chart.mount({
mount: '#chart',
symbol: 'AAPL',
interval: '1D',
datafeed,
debug: true, // structured datafeed logs, delivered to console.debug by default
onError(error) {
console.error(error.code, error.source, error.message);
},
});

debug: true enables structured datafeed logging (history, realtime, and symbol-search requests). Pass a ChartDebugSettings object with a logger to route the events somewhere other than console.debug. Reproduce once, capture the relevant window, then turn verbose logging off.

Symptom-led sequences

Each symptom below lists the first diagnostic action, the signal that proves the boundary is healthy, the likely owner when it is not, and the evidence to collect before escalating.

Chart never mounts

  • First action: check whether widget.ready() resolves and whether onError received a ChartError with code widget.mount or engine.unsupported. Confirm the mount element exists and has non-zero size, and that the SDK stylesheet and assets loaded.
  • Expected signal: ready() resolves and the mount contains a canvas.
  • Likely owner: host initialization (bad mount target, missing assets, or a rejected widget option).
  • Escalation evidence: the ChartError code and message, the widget options object (redacted), and the mount element's computed dimensions.

No data or blank chart

  • First action: await chart.dataReady() and, with debug: true, trace the resolveSymbol and loadBars request/response pairs for the active symbol and interval.
  • Expected signal: one terminal response per request — bars, an intentional empty result, or a structured error (datafeed.resolveSymbol, datafeed.loadBars, datafeed.request-failed).
  • Likely owner: the datafeed adapter; if bars return but nothing draws, compare the resolved symbol's timezone, session, and price scale.
  • Escalation evidence: the failing request parameters, the terminal response or error code, and one sample bar with its timestamp.

Realtime stops updating

  • First action: confirm exactly one active subscribeRealTimeBars subscription for the symbol/interval and that its unsubscribe function has not been called; watch for datafeed.session-disconnected or datafeed.session-error reports.
  • Expected signal: monotonically valid bar updates on the single active subscription after historical bars complete.
  • Likely owner: datafeed transport (dropped stream, missed resubscribe after reconnect, or duplicate subscriptions clobbering each other).
  • Escalation evidence: subscription create/cancel timestamps, the last update received, and any session error codes.

Storage save fails

  • First action: catch the thrown SdkError from the save call (for example widget.chartLayouts().saveAs(...)) and read its code: storage.unavailable, storage.revision-conflict (DrawingRevisionConflictError), storage.permission-denied (DrawingPermissionError), or storage.stale-response.
  • Expected signal: the adapter returns the saved payload and a subsequent load round-trips it unchanged.
  • Likely owner: the storage adapter or backend (revision race, auth scope, or an adapter returning stale data).
  • Escalation evidence: layout/chart IDs, the error code and details, and the adapter's raw response for the failing operation.

Chart broker panel is empty

  • First action: verify widget.trading().connect() resolved, then call widget.trading().getState() and compare it with what the panel shows; check for thrown trading.* codes such as trading.adapter-contract-invalid or trading.adapter-unsupported.
  • Expected signal: getState() returns the accounts, orders, and positions the adapter reports, and accepted mutations are followed by authoritative list updates.
  • Likely owner: the broker adapter (connect never completed, a contract mismatch, or state events not emitted after mutations).
  • Escalation evidence: the connect result, the getState() snapshot, and the first trading.* error code with its details.

Licensing or authorization fails

  • First action: inspect the thrown ChartAuthorizationError — its code names the failure: authorization.token-expired, authorization.required, authorization.entitlement-denied, authorization.verification-failed, and the other authorization.* codes. Inspect the host backend's lease exchange response and expiry — never the secret itself.
  • Expected signal: the browser receives a renewable lease with the expected audience and expiry, and the chart initializes.
  • Likely owner: the host backend (expired or mis-scoped lease) or the deployment's entitlement configuration.
  • Escalation evidence: the authorization error code, lease expiry and audience, and the backend exchange status — with all tokens redacted.

Teardown leaks

  • First action: count active datafeed/quote/session subscriptions and event listeners before and after widget.destroy(); a subsequent API call that throws widget.destroyed confirms the widget itself shut down.
  • Expected signal: every unsubscribe function returned by the feed's subscribe* methods is invoked and counts return to the pre-mount baseline.
  • Likely owner: host lifecycle (destroy skipped on route change, or a fixture holding subscriptions outside the widget).
  • Escalation evidence: before/after subscription and listener counts and the navigation sequence that leaks.

Reproduce one boundary at a time

  1. Start with the smallest stable symbol and interval.
  2. Disable unrelated optional capabilities.
  3. Capture the request, terminal response, and cleanup for the suspected boundary.
  4. Compare the public observable result with the page's verification checkpoint.
  5. Re-enable capabilities one at a time after the baseline passes.

Evidence to attach when escalating

Send the smallest reproducible bundle through the support channel named during deployment onboarding or to your TradeScript account contact. Include:

  • Exact route or minimal source reproduction.
  • Application version, SDK version, customer build fingerprint, deployed origin, and package import path.
  • Browser/OS and viewport.
  • Symbol, interval, timezone, and session selection.
  • Error code and redacted structured logs from the first failing boundary.
  • A screenshot or short recording of the visible result.
  • Whether teardown returns subscription/listener counts to baseline.

Do not attach the permanent credential, complete deployment lease, broker secret, complete customer order, or an unbounded market-data capture. Include a correlation ID so TradeScript and your integration owners can match redacted logs without sharing secrets.

Next steps

  • Monitoring and error handling — the monitoring signals, error model, and retry policy behind every symptom above.
  • Datafeeds — when initialization succeeds but bars never arrive.
  • Storage — when layouts, drawings, or settings fail to save or restore.
  • Trading — when broker state, orders, or executions do not reach the chart.
  • License model — when the package, origin, policy, or deployment record may not match.
  • Production authorization — when credential exchange or lease renewal is the failing boundary.