トラブルシューティング

一般的なチャート統合の不具合に対するコピペ可能な確認項目と修正手順。

これらの障害モードは、diagnose_chartで使用されるのと同じバージョン管理された知識から生成されています。アプリケーションに最も近い症状から始め、診断チェックを適用し、文書化されたライフサイクルと型付き配列の所有権契約を維持する修正のみを適用してください。

該当するエントリが見つからない場合は、関連するシンボルを入れ子のAPIリファレンスで確認するか、ローカルのMCPサーバーにフォーカス診断を実行するよう依頼してください。再現手順は診断手順としてのみrenderMode: "main"とanimated: falseのみに絞ってください。これは自動的な本番構成ではありません。

症状インデックス

キャンバスが空白、またはサイズがゼロです

適用対象: line, stock.

症状。 チャートはエラーを表示せずに初期化されますが、プロットが表示されないか、キャンバスの高さがゼロピクセルです。

考えられる原因。 レンダラーが初期化された時点で、キャンバスのホストに具体的な高さが設定されていませんでした。

確認すること

  • ホストとキャンバスをgetBoundingClientRect()で点検してください;幅と高さは共にゼロより大きくなければなりません。
  • チャート行がフレックスまたはグリッドの祖先要素によって折り畳まれていないか確認してください。

修正方法

  • initialize() が実行される前にホスト要素に具体的な height または min-height を設定してください。
  • キャンバスの内在的な寸法に依存せず、そのホストをキャンバスが埋めるようにしてください。

チャートに測定可能なホスト要素を与えてください

.chart-host {
  position: relative;
  width: 100%;
  height: clamp(20rem, 55vh, 34rem);
}

.chart-host > canvas {
  display: block;
  width: 100%;
  height: 100%;
}

チャートの準備が完了する前にデータが設定される

適用対象: line、stock。

症状。 最初のデータセットが表示されず、後の更新や再マウントで表示される。

考えられる原因。 バニラ統合が initialize() の完了前にデータメソッドを呼び出した、または同じキャンバスを複数回初期化した可能性があります。

確認する

  • 各チャートインスタンスについて initialize() が正確に一度だけ await されていることを確認してください。
  • フレームワークがビューを管理している場合は、マウントとアンマウントの順序を自動で扱うため公式アダプターを使用することを推奨します。
  • アダプターの準備完了は、初期化後と最初のデータ・外観・ビューポートのプロップのバッチが正常に処理された後に一度発火します。これはペイント済みフレームの通知ではありません。

修正

  • setData() または setMultiSeriesData() を呼び出す前に initialize() を待機してください。
  • 別インスタンスで同じキャンバスを再利用する前に、古いチャートを破棄してください。
  • adapter prop のインストールが拒否された場合、再マウントせずに再試行できるように修正済みの props を渡してください。一度正常にインストールされたデータは再転送されません。ターミナルレンダラーの失敗は再マウントが必要です。

バニラのライフサイクルを使用してください

const chart = new LineChart(canvas, { renderMode: "auto" });
await chart.initialize();
chart.setData(data);

// Call this when the view is permanently removed.
export function disposeChart() {
  chart.destroy();
}

Worker レンダリングはメインスレッドへフォールバックします

適用対象: line、stock。

症状。 チャートは動作するが、メインスレッドでのレンダリングにフォールバックする、またはWorkerの構築が本番環境でのみ失敗する。

考えられる原因。 Worker、OffscreenCanvas、transferControlToOffscreen、またはデプロイされたコンテンツセキュリティポリシーにより、Workerレンダラーの起動が阻止された。

確認すること

  • 一時的にsetStatsCallback()を使用して統計を検査してください。renderMode。
  • ブラウザのコンソールと worker-src Content Security Policy 指令を確認してください。

修正

  • 診断のためにモードを強制する必要がある場合を除き、renderModeは自動(auto)に設定したままにしてください。
  • アプリケーションが生成する Worker の URL を worker-src に許可し、メインスレッドのフォールバックを動作可能にしておいてください。

解決されたレンダラーを確認してください

chart.setStatsCallback((stats) => {
  console.info("Sixtyfold renderer:", stats.renderMode);
  chart.setStatsCallback(null);
});

Typed array は setData の後にデタッチされます

適用対象: line、stock。

症状。 ソースの Typed array が byteLength 0 になっている、あるいはデータが Worker 支援のチャートに渡された後に読み取れなくなる。

考えられる原因。 バルクチャートデータはWorkerモードでレンダラーに転送されます;転送されたArrayBuffersは呼び出し元を離れます。

確認する

  • バルクデータ呼び出しの直前と直後にbyteLengthを検査してください。
  • 別のサブシステムが読み取り可能なコピーを保持する必要が本当にあるか確認してください。

修正

  • バルクデータ呼び出しを所有権の移譲として扱う。
  • 別のサブシステムが保持する必要がある列のみをクローンする。既定で数百万件のデータセットを複製しないようにする。

意図的なアプリケーションのコピーを保持する

const retainedX = sourceX.slice();
const retainedY = sourceY.slice();

chart.setData({
  x: sourceX,
  y: sourceY,
  length: sourceX.length,
});

// retainedX and retainedY remain readable.

時間軸が圧縮されている、空である、または将来に大きくずれている

該当: line、stock。

症状。 目盛りに不合理な日付が表示される、表示範囲が崩壊する、またはパン操作が予測不能に動作する。

考えられる原因。 X列が有限で順序付けられたエポックミリ秒ではなく秒や文字列を使っている、あるいは観測データがソートされていなかった。

確認する

  • 最初と最後のタイムスタンプを確認し、new Date(value) で変換してください。
  • すべてのタイムスタンプが有限であることを確認してください。株式ストリーミングでは、各バッチ内および以前にキューまたは追加されたローソク足の後で、タイムスタンプが厳密に増加している必要があります。
  • ストリーミングと静的なStockChart.setData()を区別してください:静的データは単調増加または単調減少で同一タイムスタンプを含む場合があり、チャートはその順序を正規化します。

修正

  • Float64Array を作成する前にエポック秒をミリ秒に変換してください。
  • 取り込み時に ISO 日付を一度解析し、列に分割する前に完全な観測値をソートしてください。
  • 追加する前に株式ストリームの観測値の重複を除去してください。ストリーミングの追加メソッドは同じタイムスタンプの既存のキャンドルを更新しません。

取り込み時にタイムスタンプを正規化する

const timestamp = Float64Array.from(rows, (row) => {
  const value = Date.parse(row.recordedAt);
  if (!Number.isFinite(value)) throw new TypeError("Invalid recordedAt value");
  return value;
});

列の長さが異なるか、数値が無効である

適用対象: line、stock。

症状。 チャートがデータセットを拒否する、予期せず切り詰める、または値を誤ったタイムスタンプで描画する。

考えられる原因。 列形式のデータが別々のフィルターやマッピングから作成されたため、時刻列と値列がもはや同じ観測を記述していません。

確認する

  • チャートを呼び出す前にすべての列の長さを比較してください。
  • バッファを転送する前に数値変換を検証してください。
  • Stock addCandles は同一サイズの6列を必要とします。addCandleBatches は転送前にチャンク一覧全体を検証します。不正なタイムスタンプや列長があると呼び出し元バッファはそのまま残ります。

修正

  • まず完全なソース観測をフィルターとソートで処理し、それから整列した型付き列に分割してください。
  • 記載されたライン系列のギャップに対してのみ明示的な NaN を使用してください。OHLCV 値は有効なキャンドルのままでなければなりません。

転送前に位置ずれした列を拒否する

const lengths = [timestamp.length, open.length, high.length, low.length, close.length, volume.length];
if (!lengths.every((length) => length === lengths[0])) {
  throw new RangeError(`OHLCV columns are misaligned: ${lengths.join(", ")}`);
}

SSR またはハイドレーションがブラウザー専用のチャート API にアクセスする

適用対象: line、stock。

症状。 window、document、Worker、または HTMLCanvasElement が利用できないためサーバー側レンダリングが例外を投げる、あるいはハイドレーションで異なるツリーが生成される。

考えられる原因。 インタラクティブなブラウザチャートがクライアントのマウント後ではなくサーバー評価中に構築された。

確認する

  • モジュールスコープまたはサーバーコンポーネント内でのチャート構築を探す。
  • サーバー側の画像生成をブラウザの操作から分離するには、@sixtyfold/ssrを使用する。

修正

  • クライアント所有のコンポーネント内で公式フレームワークアダプターを使用してください。
  • SSR中は安定したホストをレンダリングし、マウント後にのみインタラクティブなチャートを初期化してください。

クライアント境界の背後にNext.jsチャートを維持してください。

"use client";

import type { MultiSeriesData, TimeSeriesData } from "@sixtyfold/core";
import { SixtyfoldLineChart } from "@sixtyfold/react/line";

type LineData = TimeSeriesData | MultiSeriesData;

export function ChartPanel({ data }: { data: LineData }) {
  return <SixtyfoldLineChart data={data} options={{ renderMode: "auto" }} />;
}

ナビゲーション後も Worker またはメモリが残る

適用対象: line、stock。

症状。 ビューを繰り返し開くとメモリが増加する、またはナビゲーション後も古いチャートのレンダリングが続く。

考えられる原因。 所有するビューが削除された際に、バニラチャートまたは一時的なデータ Worker が破棄されなかった。

確認

  • 複数回のマウント/アンマウントサイクルの前後で、ブラウザーのヒープスナップショットを記録してください。
  • 保持されているチャートインスタンス、Worker、オブザーバー、またはデコード済みソース配列を探してください。

修正

  • バニラチャートの各インスタンスに対して destroy() を正確に一度だけ呼び出してください。
  • 一時的なフェッチ/デコード Worker は最終転送後に終了してください。公式のフレームワークアダプターはチャート用 Worker を自動的に破棄します。

チャートおよびインジェスト用 Worker を解放する

return () => {
  dataWorker?.terminate();
  chart.destroy();
};

操作が遅い、またはフレームが落ちる

適用対象: line、stock。

症状。 ズーム、パン、初期デコード、またはストリーミング更新が目に見えてブロックされる、あるいは目標フレームレートを満たさない。

考えられる原因。 メインスレッドがあまりにも多くのデータをデコードまたはリシェイプしている、チャートがフォールバックレンダラーにフォールバックしている、または表示されている作業負荷がターゲットデバイスが維持できる描画パス数を超えている。

確認する

  • 統計を確認してください。renderMode、frameTime、可視作業、および実際の操作シーケンス中の詳細度準備状況。
  • フェッチ、デコード、変換、転送、およびレンダリングを個別にプロファイルしてください。

修正

  • renderMode auto を使用し、専用のデータWorkerでカラム型のTypedArrayを準備して一度転送し、その取り込みWorkerを終了してください。
  • 代表的なブラウザ、DPR、シリーズ数、ジェスチャーでベンチマークを行ってください。60 FPSは設計目標であり、デバイスに依存しない保証ではありません。

アクティブなレンダリングパスを計測してください

chart.setStatsCallback((stats) => {
  console.table({
    mode: stats.renderMode,
    fps: stats.fps,
    frameTime: stats.frameTime,
    ready: stats.lodReady,
  });
}, { intervalMs: 250 });

ズームが落ち着いた後に線の詳細度が急に変化する

対象: line。

症状。 ビューポートは滑らかにアニメーションしますが、ジェスチャー終了時にラインテクスチャが再び変化します。

考えられる原因。 表示密度またはグリッドの再ベース化がワークロードに対して過剰に攻撃的であるか、アプリケーションコードがアニメーション完了後にデータや外観を置き換えています。

確認すること

  • プレゼンテーション密度、グリッド差分、およびクエリ訪問を監視しながら、同じビューポートシーケンスをリプレイしてください。
  • アニメーションが収束した後に、アプリケーション側で setData()、setAppearance()、またはビューポートの復元が行われていないか確認してください。

修正

  • まずはアダプティブモード、密度 0.75、rebaseRatio 1.25、quantizationStep 0.25 で開始してください。
  • setLODOptions() を使って一度に一つの係数を調整してください。コストの高い範囲塗りや特に大規模なマルチシリーズ作業には密度 0.25 を使用してください。

チャートを再作成せずに表示を調整する

chart.setLODOptions({
  mode: "adaptive",
  density: 0.75,
  rebaseRatio: 1.25,
  quantizationStep: 0.25,
});

欠損観測値をまたいで線が接続される

対象: line。

症状。 測定が存在しない区間を視覚的に線が横切る。

考えられる原因。 欠測観測値が揃った NaN ギャップとして表現されず、削除されたかゼロに置き換えられました。

確認する

  • 表示される切れ目が必要な場合、共有された X 列が欠落区間を含んでいることを確認してください。
  • 取り込み処理が null 値をゼロに変換したかどうかを確認してください。

修正

  • X位置を揃えたまま、欠損する線の値をNumber.NaNとしてエンコードしてください。
  • OHLCVローソク足を合成したり、市場のクローズを接続したりしないでください。株式のタイムスケール挙動は観測されたローソク足によって決まります。

実際のライン系列ギャップを表現する

const data = {
  x: new Float64Array([0, 1, 2, 3]),
  y: new Float64Array([12, Number.NaN, Number.NaN, 18]),
  length: 4,
};