name: quantlab-debugging description: Gunakan skill ini saat menghadapi bug, error kompilasi, test failures, atau perilaku tidak terduga di QuantLab. Mencakup debugging Rust, Svelte, Astro, CI/CD, dan production issues. Gunakan pendekatan sistematis investigation sebelum fix.
QuantLab Debugging Skill
Skill ini memandu agent dalam mendiagnosis dan memperbaiki masalah di seluruh stack QuantLab: Rust backend, Svelte/Astro frontend, CI/CD pipeline, dan production server.
๐ฏ Kapan Skill Ini Diaktifkan
Aktifkan OTOMATIS jika:
- Ada error kompilasi Rust (
cargo check,cargo build,cargo test) - Ada error build frontend (
npm run build, TypeScript errors) - Playwright test gagal
- CI/CD workflow gagal (GitHub Actions)
- Production server error atau crash
- Endpoint return error atau data salah
- WebSocket tidak connect
- Performance degradasi
๐ Framework Debugging: DAMP
Sebelum menulis kode fix, selalu lakukan:
D - Diagnose: Reproduce error, baca pesan error lengkap
A - Analyze: Identifikasi root cause, bukan hanya symptom
M - Map: Petakan semua file/sistem yang terdampak
P - Plan: Rencanakan fix dengan minimal impact
JANGAN langsung fix tanpa diagnosis!
๐ฆ Debug: Rust Compilation Errors
Error: Missing Field in AppState
error[E0063]: missing field `new_field` in initializer of `AppState`
--> src/main.rs:47:18
Investigation Protocol:
# 1. Cari semua AppState instantiation
grep -rn "AppState {" backend/rust-api/src/
# 2. Check definisi AppState di lib.rs
cat backend/rust-api/src/lib.rs | grep -A 30 "pub struct AppState"
# 3. Update semua lokasi
# - src/lib.rs (SSOT definition)
# - src/main.rs (main instantiation)
# - src/routes.rs#test_state() (test helper)
# - tests/common/mod.rs (test common)
Error: Trait Not Implemented
error[E0277]: `MyProvider` doesn't implement `DataProvider`
note: required for `Box<MyProvider>` to implement `DataProvider`
Investigation Protocol:
# 1. Lihat definisi trait di base.rs
cat backend/rust-api/src/data/providers/base.rs
# 2. Check semua required methods
# Trait DataProvider requires:
# fn name(&self) -> &str
# async fn fetch(&self, ...) -> Result<Vec<OHLCV>, DataError>
# async fn transform(&self, data: &[OHLCV]) -> Vec<f64>
# impl Debug
# 3. Check implementasi yang gagal
# Pastikan return type cocok, terutama error type!
# DataError vs AppError โ beda!
Error: Unused Import / Variable (Clippy)
error[unused_imports]: unused import: `chrono::Timelike`
warning[...]: variable `x` is assigned but never used
Fix:
// Untuk unused import:
// Hapus baris import, JANGAN pakai #[allow(unused_imports)]
// Untuk unused variable di production:
// Pakai _ prefix: let _result = some_fn();
// Atau gunakan .ok() untuk Result yang sengaja diabaikan
// Di test code:
// let result = complex_fn();
// assert!(result.is_ok()); // sekarang result terpakai
Error: Lifetime / Borrow Checker
error[E0502]: cannot borrow `cache` as mutable because it is also borrowed as immutable
Common Fix Patterns:
// PATTERN 1: Clone before borrow
let owned = arc_value.clone();
// sekarang pakai owned, bukan arc_value
// PATTERN 2: Scope borrow
{
let borrowed = &data;
// pakai borrowed di sini
} // borrow ends here
data.push(new_item); // sekarang boleh mutasi
// PATTERN 3: Arc<RwLock<T>> untuk shared mutable state
let cache: Arc<RwLock<HashMap<K, V>>> = Arc::new(RwLock::new(HashMap::new()));
// Read:
let guard = cache.read().await;
let val = guard.get(&key);
// Write:
let mut guard = cache.write().await;
guard.insert(key, value);
Error: Async in Sync Context
error[E0728]: `await` is only allowed inside `async` functions and blocks
Fix:
// SALAH โ
fn sync_function() {
let result = async_fn().await; // tidak bisa!
}
// BENAR โ
โ Opsi 1: Jadikan async
async fn async_function() {
let result = async_fn().await;
}
// BENAR โ
โ Opsi 2: spawn_blocking untuk cpu-heavy sync code
pub async fn compute_heavy() {
let result = tokio::task::spawn_blocking(|| {
heavy_sync_computation() // code sync biasa
}).await.unwrap();
}
// BENAR โ
โ Opsi 3: tokio::runtime untuk test
#[test]
fn test_async_behavior() {
let rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(async_fn());
assert!(result.is_ok());
}
๐ฅ๏ธ Debug: Frontend Build Errors
Error: Svelte 5 Runes in .ts file
Error: $state is not defined
at SomeFile.ts:15
Root Cause: Svelte 5 runes ($state, $derived, $effect) hanya valid di .svelte atau .svelte.ts files.
Fix:
# Rename file yang pakai runes
mv src/lib/stores/websocket.ts src/lib/stores/websocket.svelte.ts
# Update semua import
grep -rn "from.*websocket.ts" src/
# Replace: import { ... } from '.../websocket'
# Dengan: import { ... } from '.../websocket.svelte'
Error: SciChart SSR Error
ReferenceError: WebAssembly is not defined
Root Cause: SciChart menggunakan WASM yang tidak bisa run di SSR (server-side render).
Fix:
<!-- SALAH โ โ static import di top level -->
import { SciChartSurface } from 'scichart';
<!-- BENAR โ
โ dynamic import dalam onMount -->
<script>
import { onMount } from 'svelte';
onMount(async () => {
// Ini hanya run di browser, tidak di SSR
const { SciChartSurface } = await import('scichart');
const { wasmContext, sciChartSurface } = await SciChartSurface.create(divId);
});
</script>
Error: TypeScript Type Mismatch
Type 'string | undefined' is not assignable to type 'string'
Fix Patterns:
// Option 1: Non-null assertion (jika yakin tidak null)
const value = someObj.field!;
// Option 2: Default value
const value = someObj.field ?? 'default';
// Option 3: Type guard
if (someObj.field !== undefined) {
const value = someObj.field; // TypeScript tahu bukan undefined di sini
}
// Option 4: Optional chaining + nullish coalescing
const value = someObj?.nested?.field ?? 0;
Error: Missing Module (node_modules corrupt)
Error: Cannot find module 'mdast-util-gfm'
Fix:
cd frontend
# Clean install
rm -rf node_modules package-lock.json
npm install
# Jika masih error
npm cache clean --force
npm install
๐ง Debug: Test Failures
Pattern: Rust Test Gagal karena Environment
thread 'test_with_auth' panicked: 'missing env var AUTH_ENABLED'
Pattern Fix:
// SALAH โ โ baca dari env (non-deterministic di CI)
fn build_test_app() -> Router {
let config = AppConfig::from_env(); // bisa beda di CI vs local
// ...
}
// BENAR โ
โ explicit test config
fn build_test_app_with_auth() -> Router {
let config = AppConfig {
auth_enabled: true,
supabase_jwt_secret: "test-secret-at-least-32-chars-here".to_string(),
// ... other fields dengan default test values
};
// ...
}
Pattern: Playwright Test Timeout
TimeoutError: waiting for selector 'h1' when timeout 30000ms exceeded
Investigation:
// 1. Tambah screenshot saat failure
test('page loads', async ({ page }) => {
await page.goto('/some-page');
// Debug: screenshot untuk lihat state
await page.screenshot({ path: 'debug-screenshot.png' });
const h1 = page.locator('h1');
await expect(h1).toBeVisible({ timeout: 10_000 });
});
// 2. Cek network request
test('api loads', async ({ page }) => {
const responsePromise = page.waitForResponse('**/v1/health');
await page.goto('/dashboard');
const response = await responsePromise;
console.log('API status:', response.status());
});
๐จ Debug: Production Issues
Server Down / No Response
# 1. Check service running
ssh ubuntu@54.251.201.70
sudo systemctl status quantlab-api
# 2. Lihat error logs
sudo journalctl -u quantlab-api -n 100 --no-pager
# 3. Check resources
free -m # RAM usage
df -h # Disk usage
top -b -n 1 # CPU usage
# 4. Check port
sudo ss -tlnp | grep 8080
# 5. Restart jika perlu
sudo systemctl restart quantlab-api
Wrong Data / Stale Response
Kemungkinan penyebab:
# 1. Cache tidak expire? Cek TTL
grep -n "expires_at\|cache_ttl\|TTL" backend/rust-api/src/services/regime_service.rs
# 2. Binance API error? Pakai MockDataProvider?
sudo journalctl -u quantlab-api | grep -i "binance\|mock\|fallback"
# 3. Environment variable salah?
sudo grep BINANCE_API_KEY /opt/quantlab/.env
# 4. Restart fresh (clear in-memory cache)
sudo systemctl restart quantlab-api
CORS Error di Production
Access to fetch at 'http://api...' from origin 'https://quantlab...' blocked
Fix:
# 1. SSH ke EC2
ssh ubuntu@54.251.201.70
# 2. Check ALLOWED_ORIGINS
grep ALLOWED_ORIGINS /opt/quantlab/.env
# Harus: ALLOWED_ORIGINS='["https://quantlab.bamsbung.com"]'
# Biasa masalah: JSON invalid (double quotes stripped)
# 3. Fix format
# SALAH: ALLOWED_ORIGINS=["https://example.com"]
# BENAR: ALLOWED_ORIGINS='["https://example.com"]'
# 4. Restart
sudo systemctl restart quantlab-api
# 5. Test CORS
curl -H "Origin: https://quantlab.bamsbung.com" \
-H "Access-Control-Request-Method: GET" \
-v http://localhost:8080/v1/health 2>&1 | grep -i "access-control"
๐ Debug: Performance Issues
Endpoint Lambat (> 500ms)
// Tambah timing instrumentation
pub async fn slow_endpoint(...) {
let t0 = Instant::now();
let data = fetch_data().await?; // bergantung network
let t1 = Instant::now();
println!("fetch_data: {:?}", t1 - t0);
let result = compute_heavy(&data); // bergantung CPU
let t2 = Instant::now();
println!("compute_heavy: {:?}", t2 - t1);
// Dari log ini kita tahu bottleneck ada di fetch atau compute
}
Common Fixes:
// 1. CPU-heavy โ spawn_blocking
let result = tokio::task::spawn_blocking(move || {
compute_hurst_exponent(&prices) // tidak block async runtime
}).await?;
// 2. Multiple requests โ join_all (parallel)
let (regime, trade, portfolio) = tokio::join!(
fetch_regime(&asset),
fetch_trade_analysis(),
fetch_portfolio_metrics()
);
// 3. Add cache (regime berubah lambat)
if let Some(cached) = regime_cache.get(&key) {
return Ok(cached); // < 1ms vs 200ms compute
}
Memory Usage Tinggi
# Monitor RSS per menit
while true; do
ps aux | grep quantlab-api | grep -v grep | awk '{print $6" KB RSS"}'
sleep 60
done
# Jika memory terus naik โ memory leak!
# Kemungkinan: cache tidak evict, WebSocket connection tidak cleanup
๐ ๏ธ Debug Toolkit: Quick Commands
Rust Debugging
# Check compilation
cargo check 2>&1 | head -50
# Run tests dengan output
cargo test -- --nocapture 2>&1 | head -100
# Test satu file spesifik
cargo test engine::hurst::tests
# Check dependencies
cargo tree | grep -i "duplicate"
# Security audit
cargo audit
# Find dead code
cargo check 2>&1 | grep "dead_code"
Frontend Debugging
# Type check saja
npx tsc --noEmit
# Build dengan verbose
npm run build -- --verbose 2>&1 | tail -50
# Check bundle size
npm run build && du -sh dist/
# Run single test
npx playwright test tests/specific.spec.ts
npx playwright test --grep "test name pattern"
# Debug mode (headed browser)
npx playwright test --headed --slow-mo 500
Production Debugging
# Real-time log monitor
ssh ubuntu@54.251.201.70 "sudo journalctl -u quantlab-api -f"
# Check specific error pattern
ssh ubuntu@54.251.201.70 "sudo journalctl -u quantlab-api | grep -i 'error\|panic\|WARN'"
# Performance stats
ssh ubuntu@54.251.201.70 "top -bn1 | head -20 && free -m"
# API health verbose
curl -v http://54.251.201.70:8080/v1/health 2>&1
# Test CORS preflight
curl -H "Origin: https://quantlab.bamsbung.com" \
-X OPTIONS \
-v http://54.251.201.70:8080/v1/health 2>&1
๐ Error Quick Reference Table
| Error Pattern | Root Cause | Quick Fix |
|---|---|---|
missing field '...' in AppState |
Field baru di lib.rs belum diupdate di main.rs/tests | Update semua AppState instantiation |
trait bound not satisfied |
Trait method belum implement, atau return type salah | Check base.rs trait definition |
$state is not defined |
Svelte rune di .ts file biasa | Rename ke .svelte.ts |
WebAssembly is not defined |
SciChart di-import statically (SSR) | Pindah ke dynamic import dalam onMount |
ALLOWED_ORIGINS invalid JSON |
dotenvy strips double quotes | Wrap dengan single quotes di .env |
CRLF in .env |
Copy-paste atau SCP dari Windows | sed -i 's/\r//' .env |
Port 8080 timeout |
EC2 firewall closed | Buka port 8080 di AWS Console |
cargo audit --ignore fail |
sqlx-mysql active | Check cargo tree -i sqlx-mysql |
401 Unauthorized |
JWT expired atau salah format | Check Supabase JWT secret dan token format |
504 Gateway Timeout |
DATABASE_URL tidak ada atau Supabase down | Check DATABASE_URL dan Supabase dashboard |
SciChart memory leak |
surface.delete() tidak dipanggil di onDestroy | Tambah cleanup di onDestroy |
npm module not found |
node_modules corrupt | rm -rf node_modules && npm install |
๐ฆ Eskalasi Decision Tree
Ketemu bug/error
Step 1: Baca error message LENGKAP (bukan hanya baris pertama)
โ Biasanya ada "note:" atau "help:" yang memberikan petunjuk fix
Step 2: Reproduce di lokal dulu
โ Jangan langsung fix di production!
Step 3: Isolasi: mana yang bermasalah?
โ Backend? Frontend? CI/CD? Production server?
Step 4: Check apakah bug ini pernah terjadi dan ada dokumentasinya
โ Cek DECISION_LOG.md, TASK_BOARD.md, CHANGELOG.md
Step 5: Fix dengan perubahan MINIMAL dulu
โ Jangan refactor sekalian saat debugging โ nanti bisa introduce bug baru
Step 6: Verify fix tidak break yang lain
โ cargo test + npm run build + playwright test
Step 7: Document jika ini edge case / gotcha yang mungkin berulang
โ Tambah ke DECISION_LOG.md atau TROUBLESHOOTING.md