| name | debugging |
| description | 当用户要求"调试这个"、"修复bug"、"排查问题"、"不工作"、"出错了"、"调查问题"、"性能问题"、"类型错误"、"Tauri 通信失败"、"断点调试"、"日志分析"、"性能分析"、"内存泄漏"、"死锁",或者提到"调试"、"debugging"、"bug"、"问题"、"崩溃"、"错误"、"配方优化失败"、"HiGHS 求解器问题"时使用此技能。用于诊断和修复 Rust、React、数据库或 Tauri 集成代码中的问题。 |
| version | 2.1.0 |
Debugging Skill
Systematic debugging strategies for diagnosing and fixing issues in Tauri applications.
Overview
This skill provides debugging guidance for:
- Rust backend issues: Panics, errors, async problems, database failures
- React frontend issues: Runtime errors, UI problems, state management issues
- Integration problems: Tauri command failures, type mismatches, serialization errors
- Database issues: Query failures, connection problems, migration errors
- Performance issues: Slow operations, memory leaks, blocking calls
When This Skill Applies
This skill activates when:
- Application crashes or panics
- Functions return errors
- UI doesn't work as expected
- Tests are failing
- Performance is degraded
- Data is incorrect or corrupted
- Features don't work together properly
Debugging Framework
The Scientific Method
- Observe: What exactly is happening?
- Formulate Hypothesis: What could be causing this?
- Test Hypothesis: How can we verify?
- Analyze Results: Does this confirm or reject hypothesis?
- Iterate: If not solved, form new hypothesis
Systematic Debugging Process
┌─────────────────┐
│ 1. Define Issue │
│ What is the │
│ symptom? │
└────────┬────────┘
│
▼
┌─────────────────┐
│ 2. Gather Info │
│ Error msg? │
│ Stack trace? │
│ Logs? │
└────────┬────────┘
│
▼
┌─────────────────┐
│ 3. Reproduce │
│ Can we make │
│ it happen │
│ consistently?│
└────────┬────────┘
│
▼
┌─────────────────┐
│ 4. Isolate │
│ Narrow down │
│ location │
└────────┬────────┘
│
▼
┌─────────────────┐
│ 5. Fix & Test │
│ Apply fix │
│ Verify it │
│ works │
└─────────────────┘
Common Issues & Solutions
Rust Backend Issues
Issue: "Function not found" for Tauri Command
Symptom:
Error: Failed to call command 'get_formula'
Diagnosis Steps:
- Check if
#[tauri::command] attribute is present
- Check if command is registered in
main.rs
- Check if
#[specta::specta] attribute is present
- Regenerate types:
cargo run
Solution:
#[tauri::command]
#[specta::specta]
pub async fn get_formula(id: i64, state: State<'_, TauriAppState>) -> ApiResponse<Formula> {
}
fn main() {
tauri::Builder::default()
.invoke_handler(tauri::generate_handler![
get_formula,
])
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
Issue: Database Lock Error
Symptom:
Error: database is locked
or
Error: database table is locked
Diagnosis:
Solutions:
Enable WAL Mode:
sqlx::query("PRAGMA journal_mode=WAL")
.execute(&pool)
.await?;
sqlx::query("PRAGMA busy_timeout=5000")
.execute(&pool)
.await?;
Ensure Transaction Cleanup:
let mut tx = pool.begin().await?;
match operation(&mut tx).await {
Ok(result) => {
tx.commit().await?;
Ok(result)
}
Err(e) => {
Err(e)
}
}
Issue: Async Runtime Panic
Symptom:
thread 'main' has overflowed its stack
or
panic: cannot drop in runtime context
Diagnosis:
- Look for blocking calls in async functions
- Check for deep recursion
- Find CPU-intensive operations without
.await
Solution:
pub async fn bad() {
std::thread::sleep(Duration::from_secs(1));
let result = expensive_cpu_calculation();
}
pub async fn good() {
tokio::time::sleep(Duration::from_secs(1)).await;
let result = tokio::task::spawn_blocking(|| {
expensive_cpu_calculation()
}).await?;
}
React Frontend Issues
Issue: "Too many re-renders"
Symptom:
Warning: Too many re-renders. React limits the number of renders to prevent an infinite loop.
Diagnosis Steps:
- Check for state updates in render body
- Check for missing dependencies in
useEffect
- Check for callbacks created in render
Solution:
export const BadComponent: React.FC = () => {
const [count, setCount] = useState(0);
setCount(count + 1);
return <div>{count}</div>;
};
export const GoodComponent: React.FC = () => {
const [count, setCount] = useState(0);
useEffect(() => {
setCount(1);
}, []);
return <div>{count}</div>;
};
Issue: State Not Updating
Symptom:
setState(newValue);
console.log(state);
Diagnosis:
- State updates are asynchronous
- React batches updates
Solution:
setState(newValue);
console.log(state);
setState(newValue);
useEffect(() => {
console.log(state);
}, [state]);
setState(prev => prev + 1);
Issue: Hooks Called in Wrong Order
Symptom:
Error: Invalid hook call. Hooks can only be called inside of the body of a function component.
Diagnosis:
- Hooks in conditions
- Hooks in loops
- Hooks in nested functions
Solution:
if (condition) {
const [value, setValue] = useState(0);
}
const [value, setValue] = useState(0);
if (condition) {
}
Tauri Integration Issues
Issue: Type Mismatch Error
Symptom:
Error: Type 'string' is not assignable to type 'number'
Diagnosis Steps:
- Check Rust DTO field types
- Check
bindings.ts generated types
- Check for
#[serde(alias)] if needed
- Verify
#[specta(inline)] is present
Solution:
#[derive(Serialize, Deserialize, Type, Clone)]
#[specta(inline)]
pub struct CreateFormulaDto {
#[serde(alias = "formulaName")]
pub name: String,
#[serde(alias = "formulaId")]
pub id: i64,
}
const result = await commands.createFormula({
name: "Test",
id: 123,
});
Issue: Command Returns Success but Data is Null
Symptom:
const result = await commands.getFormula(123);
console.log(result);
Diagnosis:
- Check if
ApiResponse<T> wrapping is correct
- Verify
api_ok() is used correctly
Solution:
#[tauri::command]
pub async fn get_formula(id: i64) -> Formula {
}
#[tauri::command]
pub async fn get_formula(id: i64) -> ApiResponse<Formula> {
match formula_service.get(id).await {
Ok(formula) => api_ok(formula),
Err(e) => api_err(format!("获取失败: {}", e)),
}
}
Database Issues
Issue: "No such table" Error
Symptom:
Error: no such table: formulas
Diagnosis Steps:
sqlite3 feed_formula.db ".schema formulas"
ls -la migrations/
Solution:
sqlx migrate run --database-url sqlite:feed_formula.db
sqlx::migrate!("./migrations")
.run(&pool)
.await
.expect("Failed to run migrations");
Issue: Query Returns Empty Results
Symptom:
let result = sqlx::query_as!(Material, "SELECT * FROM materials")
.fetch_all(&pool)
.await?;
Diagnosis:
sqlite3 feed_formula.db "SELECT COUNT(*) FROM materials"
sqlite3 feed_formula.db "SELECT * FROM materials LIMIT 5"
Common Causes:
- Different database file (check path)
- Uncommitted transaction
- Wrong WHERE clause
Solution:
let db_path = std::path::Path::new("feed_formula.db");
println!("Using database: {:?}", db_path.canonicalize());
let mut tx = pool.begin().await?;
tx.commit().await?;
Debugging Tools & Techniques
1. Logging Strategy
Rust (using tracing):
use tracing::{info, warn, error, debug, instrument};
#[instrument(skip(self))]
pub async fn optimize_formula(&self, formula_id: i64) -> Result<Formula> {
info!(formula_id, "Starting optimization");
let formula = self.get_formula(formula_id).await
.context("Failed to load formula")?;
debug!(material_count = formula.materials.len(), "Formula loaded");
let result = self.run_optimization(&formula).await?;
info!(cost = result.total_cost, "Optimization complete");
Ok(result)
}
React (no console.log):
import { message } from 'antd';
message.info(`Loaded ${data.length} items`);
{process.env.NODE_ENV === 'development' && (
<Alert
type="info"
message="Debug Info"
description={<pre>{JSON.stringify(data, null, 2)}</pre>}
/>
)}
2. Debug Assertions
Rust:
debug_assert!(price >= 0.0, "Price cannot be negative");
assert!(
materials.len() <= 100,
"Too many materials: {}", materials.len()
);
TypeScript:
function isFormula(data: unknown): data is Formula {
return (
typeof data === 'object' &&
data !== null &&
'id' in data &&
'name' in data
);
}
if (isFormula(result)) {
console.log(result.name);
}
3. Breakpoints & Inspection
Rust (using debugger):
rustup component add rust-src
rust-lldb -- target/debug/cacrfeedformula
(lldb) breakpoint set --file src/formula/service.rs --line 42
(lldb) run
(lldb) print formula_id
(lldb) continue
React:
useEffect(() => {
debugger;
const data = await fetchData();
setState(data);
}, []);
4. Binary Search Debugging
Narrow down problematic code:
#[tauri::command]
pub async fn complex_operation(dto: Dto) -> ApiResponse<Result> {
let result1 = step1(&dto).await?;
api_ok(result1)
}
Performance Debugging
Identifying Slow Operations
Rust:
use std::time::Instant;
pub async fn slow_function() -> Result<()> {
let start = Instant::now();
let data = fetch_data().await?;
println!("fetch_data: {:?}", start.elapsed());
let result = process_data(&data)?;
println!("process_data: {:?}", start.elapsed());
Ok(())
}
Flamegraphs:
cargo install flamegraph
cargo flamegraph --bin cacrfeedformula
open flamegraph.svg
React Profiler:
import { Profiler } from 'react';
<Profiler id="FormulaList" onRender={(id, phase, actualDuration) => {
if (process.env.NODE_ENV === 'development') {
console.log(`${id} (${phase}) took ${actualDuration}ms`);
}
}}>
<FormulaList />
</Profiler>
Debugging Checklist
Initial Assessment
Information Gathering
Hypothesis & Test
Fix & Verify
Quick Reference
Common Debug Commands
cargo test
cargo test -- --nocapture
RUST_LOG=debug cargo run
rust-lldb target/debug/binary
sqlite3 feed_formula.db "SELECT * FROM formulas LIMIT 5"
sqlite3 feed_formula.db ".schema"
npm run dev
npm run lint
npm run type-check
Error Message Keywords
| Keyword | Likely Cause | Action |
|---|
unwrap() | Panic on None/Err | Use proper error handling |
borrow | Borrow checker issue | Check lifetimes, use references |
async | Runtime/blocking mismatch | Use await or spawn_blocking |
cannot find | Import/name issue | Check imports and spelling |
type mismatch | Type error | Check types, add conversions |
expected | Syntax error | Fix syntax near error location |
When to Use This Skill
Activate this skill when:
- Diagnosing errors or crashes
- Investigating unexpected behavior
- Fixing failing tests
- Tracking down bugs
- Analyzing performance issues
- Troubleshooting integration problems
- Learning from past issues