quickwit-oss/tantivy · error

StorePlugin is a built-in; use StorePluginWriter::new

Error message

StorePlugin is a built-in; use StorePluginWriter::new

What it means

StorePlugin::create_writer is deliberately unimplemented because stored-field writing is built into tantivy's segment writer; the store plugin only exposes merge. Users must create a StorePluginWriter directly with StorePluginWriter::new. Reaching this panic means the built-in plugin was dispatched through the generic plugin writer creation path.

Source

Thrown at src/store/plugin.rs:30

use crate::index::{SegmentComponent, SegmentReader};
use crate::indexer::doc_id_mapping::DocIdMapping;
use crate::plugin::{PluginMergeContext, PluginWriter, PluginWriterContext, SegmentPlugin};
use crate::schema::document::Document;
use crate::schema::Schema;
use crate::space_usage::{ComponentSpaceUsage, STORE};
use crate::store::{StoreReader, StoreWriter};
use crate::Segment;

/// Built-in segment plugin that stores and merges stored documents.
pub struct StorePlugin;

impl SegmentPlugin for StorePlugin {
    fn extensions(&self) -> &[&str] {
        &["store"]
    }

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

    fn merge(&self, ctx: PluginMergeContext) -> crate::Result<()> {
        debug_time!("write-storable-fields");
        debug!("write-storable-fields");

        let path = ctx.target_segment.relative_path(SegmentComponent::Store);
        let store_write = ctx.target_segment.index().directory().open_write(&path)?;
        let settings = ctx.settings;
        let mut store_writer = StoreWriter::new(
            store_write,
            settings.docstore_compression,
            settings.docstore_blocksize,
            settings.docstore_compress_dedicated_thread,
        )?;

        if !ctx.doc_id_mapping.is_trivial() {
            debug!("non-trivial-doc-id-mapping");

View on GitHub (pinned to b5d8deb80c)

Solutions

  1. Create the writer via StorePluginWriter::new(...) instead of the trait method.
  2. Skip built-in plugins in generic create_writer dispatch.
  3. Fix plugin registration so StorePlugin is not routed through the user-plugin path.
  4. Upgrade tantivy if triggered from maintained code paths.

Example fix

// before
let writer = store_plugin.create_writer(&ctx)?; // unimplemented!
// after
let writer = StorePluginWriter::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::<StorePlugin>()
}

Type guard

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

Prevention

When it happens

Trigger: Invoking create_writer on StorePlugin (extensions: ["store"]) directly or via generic plugin enumeration when opening segment writers.

Common situations: Custom segment writer code iterating all registered plugins including built-ins; wrong plugin factory wiring that treats StorePlugin as a user plugin.

Related errors


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