Debugging Guide Bytecode Comparison Flow Turso aims for SQLite compatibility. When behavior differs: Example Manual Query Inspection Logging Threading Issues Use stress tests with ThreadSanitizer: Deterministic Simulation Reproduce bugs with seed. Note: simulator uses legacy "limbo" naming. Stack Usage Parsing and translating an expression recurse once per level of nesting, so the stack frame size of those functions limits how deep an expression can be. Three scripts in measure stack use. Use a release build ( ): debug builds do not reuse stack slots, so their frames say little about what use…

'parse_expr_inner

Debugging Guide Bytecode Comparison Flow Turso aims for SQLite compatibility. When behavior differs: Example Manual Query Inspection Logging Threading Issues Use stress tests with ThreadSanitizer: Deterministic Simulation Reproduce bugs with seed. Note: simulator uses legacy "limbo" naming. Stack Usage Parsing and translating an expression recurse once per level of nesting, so the stack frame size of those functions limits how deep an expression can be. Three scripts in measure stack use. Use a release build ( ): debug builds do not reuse stack slots, so their frames say little about what use…

\n\n# Smallest stack that runs a SQL script, per binary. -S adds sqlite3.\nscripts/stack/min-stack.sh -S -b /tmp/tursodb-main -b target/release/tursodb deep.sql\n\n# Which functions use the stack at the deepest point (runs under lldb).\nscripts/stack/stack-profile.sh deep.sql\n```\n\nFunctions that recurse per level should be small. Move rare and large paths\ninto `#[inline(never)]` helpers, like SQLite's `SQLITE_NOINLINE`.\n\n## Architecture Reference\n\n- **Parser** → AST from SQL strings\n- **Code generator** → bytecode from AST\n- **Virtual machine** → executes SQLite-compatible bytecode\n- **Storage layer** → B-tree operations, paging\n\n## Corruption Debugging\n\nFor WAL corruption and database integrity issues, use the corruption debug tools in [scripts](./scripts).\n\nSee [references/CORRUPTION-TOOLS.md](./references/CORRUPTION-TOOLS.md) for detailed usage.","attachment_filenames":[],"attachments":[],"content_json":{"type":"doc","content":[{"type":"heading","attrs":{"level":1},"content":[{"text":"Debugging Guide","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Bytecode Comparison Flow","type":"text"}]},{"type":"paragraph","content":[{"text":"Turso aims for SQLite compatibility. When behavior differs:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":""},"content":[{"text":"1. EXPLAIN query in sqlite3\n2. EXPLAIN query in tursodb\n3. Compare bytecode\n ├─ Different → bug in code generation\n └─ Same but results differ → bug in VM or storage layer","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Example","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"# SQLite\nsqlite3 :memory: \"EXPLAIN SELECT 1 + 1;\"\n\n# Turso\ncargo run --bin tursodb :memory: \"EXPLAIN SELECT 1 + 1;\"","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Manual Query Inspection","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"cargo run --bin tursodb :memory: 'SELECT * FROM foo;'\ncargo run --bin tursodb :memory: 'EXPLAIN SELECT * FROM foo;'","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Logging","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"# Trace core during tests\nRUST_LOG=none,turso_core=trace make test\n\n# Output goes to testing/test.log\n# Warning: can be megabytes per test run","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Threading Issues","type":"text"}]},{"type":"paragraph","content":[{"text":"Use stress tests with ThreadSanitizer:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"rustup toolchain install nightly\nrustup override set nightly\ncargo run -Zbuild-std --target x86_64-unknown-linux-gnu \\\n -p turso_stress -- --vfs syscall --nr-threads 4 --nr-iterations 1000","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Deterministic Simulation","type":"text"}]},{"type":"paragraph","content":[{"text":"Reproduce bugs with seed. Note: simulator uses legacy \"limbo\" naming.","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"# Simulator\nRUST_LOG=limbo_sim=debug cargo run --bin limbo_sim -- -s \u003cseed>\n\n# Whopper (concurrent DST)\nSEED=1234 ./testing/concurrent-simulator/bin/run","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Stack Usage","type":"text"}]},{"type":"paragraph","content":[{"text":"Parsing and translating an expression recurse once per level of nesting, so the stack frame size of those functions limits how deep an expression can be. Three scripts in ","type":"text"},{"text":"scripts/stack/","type":"text","marks":[{"type":"code_inline"}]},{"text":" measure stack use. Use a release build (","type":"text"},{"text":"cargo build --release --bin tursodb","type":"text","marks":[{"type":"code_inline"}]},{"text":"): debug builds do not reuse stack slots, so their frames say little about what users run. Run each script with ","type":"text"},{"text":"-h","type":"text","marks":[{"type":"code_inline"}]},{"text":" for all options.","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"# Frame size of each function, read from its prologue. -c compares two binaries.\nscripts/stack/frame-sizes.sh 'translate::expr::'\nscripts/stack/frame-sizes.sh -c /tmp/tursodb-main 'translate_expr

Debugging Guide Bytecode Comparison Flow Turso aims for SQLite compatibility. When behavior differs: Example Manual Query Inspection Logging Threading Issues Use stress tests with ThreadSanitizer: Deterministic Simulation Reproduce bugs with seed. Note: simulator uses legacy "limbo" naming. Stack Usage Parsing and translating an expression recurse once per level of nesting, so the stack frame size of those functions limits how deep an expression can be. Three scripts in measure stack use. Use a release build ( ): debug builds do not reuse stack slots, so their frames say little about what use…

'parse_expr_inner

Debugging Guide Bytecode Comparison Flow Turso aims for SQLite compatibility. When behavior differs: Example Manual Query Inspection Logging Threading Issues Use stress tests with ThreadSanitizer: Deterministic Simulation Reproduce bugs with seed. Note: simulator uses legacy "limbo" naming. Stack Usage Parsing and translating an expression recurse once per level of nesting, so the stack frame size of those functions limits how deep an expression can be. Three scripts in measure stack use. Use a release build ( ): debug builds do not reuse stack slots, so their frames say little about what use…

\n\n# Smallest stack that runs a SQL script, per binary. -S adds sqlite3.\nscripts/stack/min-stack.sh -S -b /tmp/tursodb-main -b target/release/tursodb deep.sql\n\n# Which functions use the stack at the deepest point (runs under lldb).\nscripts/stack/stack-profile.sh deep.sql","type":"text"}]},{"type":"paragraph","content":[{"text":"Functions that recurse per level should be small. Move rare and large paths into ","type":"text"},{"text":"#[inline(never)]","type":"text","marks":[{"type":"code_inline"}]},{"text":" helpers, like SQLite's ","type":"text"},{"text":"SQLITE_NOINLINE","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Architecture Reference","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Parser","type":"text","marks":[{"type":"strong"}]},{"text":" → AST from SQL strings","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Code generator","type":"text","marks":[{"type":"strong"}]},{"text":" → bytecode from AST","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Virtual machine","type":"text","marks":[{"type":"strong"}]},{"text":" → executes SQLite-compatible bytecode","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Storage layer","type":"text","marks":[{"type":"strong"}]},{"text":" → B-tree operations, paging","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Corruption Debugging","type":"text"}]},{"type":"paragraph","content":[{"text":"For WAL corruption and database integrity issues, use the corruption debug tools in ","type":"text"},{"text":"scripts","type":"text","marks":[{"type":"link","attrs":{"href":"./scripts","title":null}}]},{"text":".","type":"text"}]},{"type":"paragraph","content":[{"text":"See ","type":"text"},{"text":"references/CORRUPTION-TOOLS.md","type":"text","marks":[{"type":"link","attrs":{"href":"./references/CORRUPTION-TOOLS.md","title":null}}]},{"text":" for detailed usage.","type":"text"}]}]},"metadata":{"date":"2026-11-02","name":"debugging","author":"@skillopedia","source":{"stars":25127,"repo_name":"turso","origin_url":"https://github.com/tursodatabase/turso/blob/HEAD/.claude/skills/debugging/SKILL.md","repo_owner":"tursodatabase","body_sha256":"a004c7b481e1b0d6c88f6d4196fdd14222b5ad884bea01c136b7bcbcb930bf16","cluster_key":"4979a8c00fae450e8468fdf6783eddfcd64f297849f223a6b790117a492096fa","clean_bundle":{"format":"clean-skill-bundle-v1","source":"tursodatabase/turso/.claude/skills/debugging/SKILL.md","text_bytes":0,"source_commit":"9c7b83b35b5626f83f65ada827df04a05306867e","skills_sh_rank":10745,"attachment_count":0,"text_attachments":0,"attachment_storage":"skill_attachments","binary_attachments":0},"cluster_size":1,"skill_md_path":".claude/skills/debugging/SKILL.md","import_metadata":{"date":"2026-11-02","author":"@skillopedia","version":"v1","category":"testing-qa","category_label":"Testing"},"exact_dupes_collapsed_into_this":0},"version":"v1","category":"testing-qa","import_tag":"skills-sh-top20k-2026-11","description":"How to debug tursodb using Bytecode comparison, logging, ThreadSanitizer, deterministic simulation, and corruption analysis tools"}},"renderedAt":1793661388474}

Debugging Guide Bytecode Comparison Flow Turso aims for SQLite compatibility. When behavior differs: Example Manual Query Inspection Logging Threading Issues Use stress tests with ThreadSanitizer: Deterministic Simulation Reproduce bugs with seed. Note: simulator uses legacy "limbo" naming. Stack Usage Parsing and translating an expression recurse once per level of nesting, so the stack frame size of those functions limits how deep an expression can be. Three scripts in measure stack use. Use a release build ( ): debug builds do not reuse stack slots, so their frames say little about what use…