ast-grep/ast-grep · critical

not implemented: tree-sitter parser is not implemented when

Error message

not implemented: tree-sitter parser is not implemented when feature flag is off.

What it means

The conditional_lang! macro in crates/language/src/parsers.rs expands to `unimplemented!("tree-sitter parser is not implemented when feature flag is off.")` when the language's cargo feature is disabled. The language enum value cannot be constructed without its tree-sitter parser, so converting it panics instead of returning a compile-time or runtime error.

Source

Thrown at crates/language/src/parsers.rs:15

//! This mod maintains a list of tree-sitter parsers crate.
//! When feature flag is on, this mod will import all dependent crates.
//! However, tree-sitter bs cannot be compiled by wasm-pack.
//! In this case, we can use a blank implementation by turning feature flag off.
//! And use other implementation.

macro_rules! conditional_lang {
  ($lang: ident, $flag: literal, $field: ident) => {{
    #[cfg(feature=$flag)]
    {
      $lang::$field.into()
    }
    #[cfg(not(feature=$flag))]
    {
      unimplemented!("tree-sitter parser is not implemented when feature flag is off.")
    }
  }};
  ($lang: ident, $flag: literal) => {
    conditional_lang!($lang, $flag, LANGUAGE)
  };
}

use ast_grep_core::tree_sitter::TSLanguage;

pub fn language_bash() -> TSLanguage {
  conditional_lang!(tree_sitter_bash, "tree-sitter-bash")
}
pub fn language_c() -> TSLanguage {
  conditional_lang!(tree_sitter_c, "tree-sitter-c")
}
pub fn language_cpp() -> TSLanguage {
  conditional_lang!(tree_sitter_cpp, "tree-sitter-cpp")
}

View on GitHub (pinned to fc2b1530db)

Solutions

  1. Enable the corresponding cargo feature for the language, e.g. `cargo install ast-grep --features <lang>` or add `features = ["<lang>"]` to the dependency in Cargo.toml, then rebuild.
  2. If using a custom build, add the language's tree-sitter parser feature to the build configuration and reinstall.
  3. Remove or gate rules/custom languages that target the disabled feature so the macro's enabled branch is used instead.

Example fix

// before (Cargo.toml)
ast-grep = { version = "0.x", default-features = true }
// after
ast-grep = { version = "0.x", features = ["swift"] } // enable the parser feature for the language you use
Defensive patterns

Strategy: validation

Validate before calling

# check the feature is enabled before shipping rules for a language
cargo metadata --no-deps --format-version 1 | jq '.packages[].features' | grep <lang>
# or in build.rs / CI:
if ! grep -q '"<lang>"' Cargo.toml; then echo "language feature <lang> not enabled"; exit 1; fi

Try / catch

// wrap language conversion so a panic becomes an error:
let lang = std::panic::catch_unwind(|| to_language(name))
  .map_err(|_| anyhow!("language '{}' requires its tree-sitter feature flag enabled", name));

Prevention

When it happens

Trigger: Requesting a language (e.g. via from_str/into through the conditional_lang! macro) whose crate feature flag is not enabled in the build, such as using a custom-language or non-default language without the matching `feature` in Cargo.toml.

Common situations: Installing ast-grep with default features then writing rules for a language behind an opt-in feature; building a trimmed-down custom ast-grep (npx/scarb/custom builds) that excluded a parser; language registered in sgconfig.yml custom_languages but parser feature disabled.

Related errors


AI-assisted analysis of ast-grep/ast-grep@fc2b1530db (2026-09-05). Data as JSON: /api/errors/c7e210538d683f95. Report an issue: GitHub.