Open-Source Wikis

/

Helix

/

How to contribute

/

Debugging

helix-editor/helix

Debugging

How to figure out what Helix is doing when something doesn't work.

Logging

Helix logs to a file using the log crate plus fern for formatting (set up in helix-term/src/main.rs::setup_logging).

Verbosity flags:

Flag Level
(none) warn
-v info
-vv debug
-vvv trace

Custom log path:

hx -vv --log /tmp/helix.log
# in another terminal
tail -f /tmp/helix.log

The default log lives at helix_loader::default_log_file() (typically ~/.cache/helix/helix.log). The :log-open typable command opens it in Helix.

When debugging from cargo run:

cargo run -- -v --log /tmp/helix.log <files>

Print debugging is the recommended starter: drop log::info!("…") calls, run with -v, follow the log.

Health check

hx --health
hx --health <language>
hx --health clipboard
hx --health all-languages

helix-term/src/health.rs reports on:

  • Configured clipboard providers and which ones work.
  • Terminal capabilities (true color, undercurl, kitty keyboard protocol).
  • Per-language tooling: language servers, formatter, debugger, query files.

hx --health is the first thing to run when "completion isn't working" or "the diff gutter is empty".

Common failure modes

"Editor doesn't start / panics on startup"

  • A bad config file. Helix prints the offending TOML and offers to continue with defaults — press Enter to skip the bad config.
  • A missing runtime directory. Set HELIX_RUNTIME or copy/symlink runtime/ to the user config dir.
  • A missing tree-sitter grammar. Run hx --grammar fetch && hx --grammar build. If you don't want grammars at all, set HELIX_DISABLE_AUTO_GRAMMAR_BUILD=1.

"Language server doesn't start"

  1. hx --health <lang> — confirms the binary is on $PATH.
  2. Check the log with -vv — LSP transport errors are logged at debug level. Look for "spawn failed", "stderr from server".
  3. Confirm the language-server entry in languages.toml matches the configured server name.
  4. Some servers need a workspace root marker (Cargo.toml, package.json); Helix picks the deepest matching directory walking up from the file.

"Tree-sitter highlighting is wrong"

  • cargo xtask query-check against just your language: cargo xtask query-check rust.
  • Check the loaded grammar version: hx --health rust shows the resolved grammar path.
  • Multiple runtime/ directories can shadow each other — the priority order in helix-loader/src/lib.rs::prioritize_runtime_dirs determines which file wins.

"Edit produced wrong cursor position"

Most cursor bugs come from Range::map with the wrong Assoc. The default After is right for typing forward; AfterWord keeps the cursor at the end of an inserted word; Before is for marks that should not move with insertions on top of them. See primitives/transaction.

"Test passes locally but fails in CI"

  • The CI uses MSRV (1.90). If you used an unstable feature, it'll fail.
  • File handle limits on macOS: see the testing page.
  • The windows runner uses crossterm. Backend differences can surface as input handling bugs.

Debugging the editor with itself

:debug-start lets you debug a binary built from the workspace using the configured DAP adapter. For Helix itself:

cargo build --profile dev
# in helix
:debug-start binary target/debug/hx

Set breakpoints with space g b, step with the keys under the space g prefix.

RUST_BACKTRACE

For panics:

RUST_BACKTRACE=1 cargo run -- <files>
RUST_BACKTRACE=full cargo run -- <files>

The integration test workflow sets RUST_BACKTRACE=1 automatically.

When you must dbg!

dbg! writes to stderr. Helix's terminal claims stdout/stderr while running, so dbg! output gets eaten. Two workarounds:

  1. Use log::info!("{:?}", x) and follow the log file.
  2. eprintln! to a log file you redirect: cargo run -- 2>/tmp/helix.err. Note this still gets garbled if the terminal is in raw mode — best for early-startup debugging.

Profiling

For CPU profiles, cargo flamegraph --profile opt --bin hx -- <files> works (you'll need flamegraph installed). The opt profile is what releases use, so the flamegraph reflects production behaviour.

For UI freezes, the most useful tool is :log-open followed by :reload-config to inspect what handlers are firing. Long-running synchronous work in a hook is the usual culprit — switch to an AsyncHook.

Asking for help

Include in your bug report:

  1. hx --version
  2. hx --health output (sanitized).
  3. Steps to reproduce.
  4. Relevant log excerpt with -vv.
  5. Your terminal emulator and OS.

The Matrix room and GitHub issues both expect this minimum.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Debugging – Helix wiki | Factory