quickwit-oss/tantivy · error

InvertedIndexPlugin is a built-in; use InvertedIndexPluginWr

Error message

InvertedIndexPlugin is a built-in; use InvertedIndexPluginWriter::new

What it means

InvertedIndexPlugin's SegmentPlugin::create_writer is intentionally unimplemented because inverted index writing is built into tantivy's core segment writer. Users must construct an InvertedIndexPluginWriter via InvertedIndexPluginWriter::new instead of routing writes through the plugin trait. Hitting this means the generic plugin machinery incorrectly dispatched writer creation for the built-in plugin.

Source

Thrown at src/index/inverted_index_plugin.rs:69

        // reallocation in the hashmap. Check if this affects performance.
        .map(|power| 1 << power)
        .take_while(|capacity| compute_table_memory_size(*capacity) < table_memory_upper_bound)
        .last()
        .ok_or_else(|| {
            crate::TantivyError::InvalidArgument(format!(
                "per thread memory budget (={per_thread_memory_budget}) is too small. Raise the \
                 memory budget or lower the number of threads."
            ))
        })
}

impl SegmentPlugin for InvertedIndexPlugin {
    fn extensions(&self) -> &[&str] {
        &["fieldnorm", "term", "idx", "pos"]
    }

    fn create_writer(&self, _ctx: &PluginWriterContext) -> crate::Result<Box<dyn PluginWriter>> {
        unimplemented!("InvertedIndexPlugin is a built-in; use InvertedIndexPluginWriter::new")
    }

    fn merge(&self, ctx: PluginMergeContext) -> crate::Result<()> {
        // Field norms first: postings merge reads them back from the target segment.
        merge_fieldnorms(&ctx)?;

        debug_time!("write-postings");
        debug!("write-postings");
        let target_segment = ctx.target_segment;
        let mut serializer = InvertedIndexSerializer::open(target_segment)?;
        let fieldnorm_data = target_segment.open_read(SegmentComponent::FieldNorms)?;
        let fieldnorm_readers = FieldNormReaders::open(fieldnorm_data)?;
        write_postings_merge(
            ctx.readers,
            ctx.schema,
            &mut serializer,
            fieldnorm_readers,
            ctx.doc_id_mapping,

View on GitHub (pinned to b5d8deb80c)

Solutions

  1. Use InvertedIndexPluginWriter::new(...) to create the writer instead of the plugin trait method.
  2. Exclude InvertedIndexPlugin from any generic plugin create_writer dispatch loop.
  3. Register only non-built-in plugins in custom writer factories.
  4. Upgrade tantivy if this arises from core code paths.

Example fix

// before
let writer = inverted_index_plugin.create_writer(&ctx)?; // unimplemented!
// after
let writer = InvertedIndexPluginWriter::new(ctx);
Defensive patterns

Strategy: type-guard

Validate before calling

fn can_create_writer(plugin: &dyn SegmentPlugin) -> bool {
    plugin.type_id() != std::any::TypeId::of::<InvertedIndexPlugin>()
}

Type guard

fn is_builtin_inverted_index(plugin: &dyn SegmentPlugin) -> bool {
    plugin.type_id() == std::any::TypeId::of::<InvertedIndexPlugin>()
}

Prevention

When it happens

Trigger: Calling create_writer on an InvertedIndexPlugin instance, directly or via generic plugin-writer plumbing that resolves a plugin by its extensions ("fieldnorm", "term", "idx", "pos").

Common situations: Custom segment writer or tooling enumerating registered plugins and calling create_writer generically; incorrect plugin registration causing the built-in plugin to be treated as user-provided.

Related errors


AI-assisted analysis of quickwit-oss/tantivy@b5d8deb80c (2026-09-05). Data as JSON: /api/errors/d82887d27e422d43. Report an issue: GitHub.