Skip to main content

Customization Troubleshooting

Use the live customization state first. It shows what the SDK accepted and what will be saved in chart state.

TradeScript indicator settings modal over a chart, showing inputs, style, visibility, and reset controls
Inspect the exact surface and state: modal tokens, form controls, chart background, pane labels, and series styling can come from different customization groups.

First diagnostic

  1. Read getCustomizationState().
  2. Inspect the rendered/provenance snapshot for the exact field.
  3. Identify the highest active precedence layer.
  4. Change the owning layer once.
  5. Verify both the live surface and a save/reload round trip.
const state = chart.customization().getCustomizationState();
console.log(state);

My override is stored but not visible

First inspection: chart.customization().trackSnapshots(...).inspect().fieldApplication — it classifies each field as applied, conditional, application-owned, stored-only, or unknown.

Expected value: the field reports applied. A stored-only or conditional result explains the symptom by itself.

Whether a group has a live chart effect depends on the bucket:

BucketLive effect
chartOverrides.mainSeries, grid, axes, sessionsApplied directly to the chart
chartOverrides.chart, panes, scalesApplied through their typed native fields: chart.background, panes.separator, scales.axis, scales.xAxis, scales.yAxis
chartOverrides.tradingApplied by trading overlays for orders, positions, and executions
styleOverrides.styles, background, crosshair, grid, separator, typed indicators, typed drawings, handles, typed candles, typed text, typed colors.gridApplied directly to the chart
styleOverrides.averageClosePriceLine, bidAskPriceLine, highLowPriceLine, previousClosePriceLineApplied by reference price-line overlays when the matching display setting and market data make the line visible
styleOverrides.toolbar, styleOverrides.modalsStored/reserved buckets — live toolbar and modal appearance uses ChartTheme.ui
SymptomFirst checkExpectedOwnerFixVerify
Value appears in getCustomizationState() but not on the charttrackSnapshots(...).inspect().fieldApplicationField classified appliedSDK override contractMove the setting to an applied bucketField reports applied and the chart repaints
A stored native value has the wrong shapevalidateCustomizationState(...) or inspect().diagnosticsEmpty diagnosticsNative customization contractReplace the value with the typed native shape before saving or replaying stateDiagnostics come back empty on the next inspect
Toolbar or modal colors ignore applyStyleOverrides(...)getCustomizationState().styleOverrides.toolbar / .modalsNothing relies on these stored bucketsTheme UI tokensUse ChartTheme.ui.button, ChartTheme.ui.modal, or scoped CSSToolbar/modal recolors after setTheme
Trading line colors do not updateOrders, positions, or executions attached to the chartOverlay data presentTrading overlay stateApply chartOverrides.trading and update the trading overlay data sourceLines restyle once overlay data exists

My candle colors do not round trip

First inspection: chart.customization().getCandleColors().

Expected value: exactly the colors you set.

Correction: use setCandleColors(...) for common candle colors instead of hand-built nested patches:

chart.customization().setCandleColors({
up: '#16a34a',
down: '#dc2626',
noChange: '#94a3b8',
});

const colors = chart.customization().getCandleColors();

Verification: getCandleColors() returns the values you set, and they survive a getState() / setState() round trip. Low-level candle overrides use the nested candles.bar shape documented by StyleOverrideSettings.

My theme changed but some series colors did not

First inspection: getCustomizationState().styleOverrides.candles and getCandleColors().

Expected value: empty when the theme should own series colors. ChartTheme is the base skin; explicit style overrides are higher precedence, so any value here pins the color across theme switches.

Correction: update or clear those overrides when switching themes.

Verification: switch the theme again — the candle colors now follow the preset.

My restored layout uses the old theme

First inspection: chart.customization().getTheme() after applyLayout(...).

Expected value: the host's product theme — but layouts include state.customization, so a saved layout that carries a theme restores that theme.

Correction: reapply the host theme after applyLayout(...) when the product theme should always win:

await chart.applyLayout(savedLayout);
chart.customization().setTheme(hostTheme);

Verification: getTheme() returns the host theme and the chart repaints with it. This is the same precedence rule used by setState(...): restored customization is state, and a later runtime customization call wins again.

My user setting overrides a default

First inspection: compare the stored UserSettingsState with getCustomizationState() — they are separate surfaces.

Expected value: loading UserSettingsState never rewrites ChartOverrideSettings, StyleOverrideSettings, or ChartTheme by itself; host code has to choose to apply a saved preference to customization.

Correction: use features.userSettings and ChartStorageAdapter for product preferences such as favorite intervals or host-defined settings. Use initialState.customization and chart.customization() for chart appearance.

Verification: reload with the user setting present — customization state is unchanged until your code applies it.

My CSS is missing in the host application

First inspection: the host bundle's imports.

Expected value: the published CSS entry point imported once:

import '@tradescript/pro/style.css';

Correction: add the import. If the host uses the compiled utility layer directly, also import @tradescript/pro/tailwind.css. For CDN or script-tag deployment, link the built CSS files alongside the UMD bundle.

Verification: chart chrome renders styled after rebuilding the application, including in a clean production installation.

My custom indicator or embed fails under CSP

First inspection: the browser console, for blocked worker-src, style-src, or frame-src entries. SDK worker-backed compute paths, bundled styles, and embedded media can all be blocked by a restrictive Content Security Policy. Trusted custom indicator modules are bundled with the host; the public SDK does not compile customer indicator source at runtime.

Expected value: no CSP violations naming SDK workers or styles.

Correction: disable the affected feature in features, provide worker clients or factories with main-thread fallback diagnostics, or update CSP to allow the exact trusted worker origin. Do not relax CSP broadly just to make chart customization work.

Verification: the console shows no CSP violations and the feature loads.

I need to know what changed

Subscribe to customization events:

const unsubscribe = chart.customization().subscribe((event) => {
if (event.type === 'overrides-change') {
console.log(event.state.chartOverrides, event.state.styleOverrides);
}
});

Widget-level event handlers also receive customization-change events.

For field-level provenance, track native snapshots:

const tracker = chart.customization().trackSnapshots('constructor');

chart.customization().applyStyleOverrides({
grid: { horizontal: { color: '#1f2937' } },
});

const inspection = tracker.inspect();
console.table(inspection.effectiveFields);
tracker.dispose();

effectiveFields shows the current field value and the source event that last changed it. fieldHistory includes cleared fields, so it can explain why a value that used to exist is no longer effective. fieldApplication separates applied, conditional, host-owned, state-only, and unknown fields. diagnostics reports invalid typed native customization values in the final snapshot, including the source event when the bad value came from tracked snapshots.