FuelLabs/fuel-core · error · anyhow::Error

Missing column. Check the schema!

Error message

Missing column. Check the schema!

What it means

Encoder::write in the parquet encoder asks the row-group writer for its next column and treats None as a schema violation ('Missing column. Check the schema!', crates/chain-config/src/config/state/parquet/encode.rs:70). The encoder is created with a single byte-array column, so this error means the parquet writer yielded no column where one was guaranteed — an internal invariant break, typically writer misuse (writing after close, reusing a writer whose state advanced after a swallowed error) or a parquet-crate version mismatch.

Source

Thrown at crates/chain-config/src/config/state/parquet/encode.rs:70

                .build()
                .expect("This is a valid schema");

        Type::group_type_builder("unimportant")
            .with_fields(vec![Arc::new(data)])
            .build()
            .expect("This is a valid schema")
    }
}

impl<W> Encoder<W>
where
    W: Write + Send,
{
    pub fn write(&mut self, elements: Vec<Vec<u8>>) -> anyhow::Result<()> {
        let mut group = self.writer.next_row_group()?;
        let mut column = group
            .next_column()?
            .ok_or_else(|| anyhow::anyhow!("Missing column. Check the schema!"))?;

        let values = elements.into_iter().map(Into::into).collect_vec();
        column
            .typed::<ByteArrayType>()
            .write_batch(&values, None, None)?;

        column.close()?;
        group.close()?;
        Ok(())
    }

    pub fn close(self) -> anyhow::Result<()> {
        self.writer.close()?;
        Ok(())
    }
}

View on GitHub (pinned to b9d4d170da)

Solutions

  1. Create a fresh Encoder per snapshot table via its constructor so the schema always contains the expected ByteArrayType column.
  2. Propagate writer errors and never reuse an encoder after a failed write.
  3. Pin the parquet crate to the version fuel-core chain-config was built and tested with.
  4. If it reproduces with a freshly constructed encoder, file an upstream bug — the encoder's own schema contract was violated.
Defensive patterns

Strategy: validation

Try / catch

match encoder.write(elements) {
    Err(e) if e.to_string().contains("Missing column") => {
        // internal invariant break: discard the writer, build a fresh Encoder, and fail loudly if it repeats
        return Err(e.context("parquet encoder invariant violated; recreate encoder"));
    }
    other => other?,
}

Prevention

When it happens

Trigger: Calling Encoder::write(elements) after the writer's row group/column state has been consumed or closed, or with a schema that ends up with zero leaf columns.

Common situations: Upgrading the parquet dependency changes next_column semantics; continuing to write after a prior error was ignored; constructing the writer outside Encoder::new so the expected single-column schema is absent.

Related errors


AI-assisted analysis of FuelLabs/fuel-core@b9d4d170da (2026-08-16). Data as JSON: /api/errors/5b0a5033eda7f726. Report an issue: GitHub.