Skip to content

[Bug] Non-struct inner field in a variant shredding schema fails with ClassCastException #9517

Description

@LuciferYang

Search before asking

  • I searched in the issues and found nothing similar.

Paimon version

master, 9c7deebbd (2.1-SNAPSHOT)

Compute Engine

Java API / Parquet read path. PaimonShreddingUtils.buildVariantSchema runs on the physical schema of a shredded variant column, from VariantShreddingReadPlanFactory.assembleVariantVector on read and VariantShreddingWritePlan on write.

Minimal reproduce step

In a variant shredding schema, every field of an object's typed_value is itself a group of value / typed_value. buildVariantSchema casts each inner field to RowType without checking it first:

for (int index = 0; index < rFields.size(); index++) {
    DataField f = rFields.get(index);
    objectSchema[index] =
            new VariantSchema.ObjectField(
                    f.name(), buildVariantSchema((RowType) f.type(), false));
}

So a physical schema whose inner field is a scalar dies on the cast:

RowType physicalType =
        RowType.of(
                new DataType[] {
                    DataTypes.BYTES(),
                    DataTypes.BYTES(),
                    RowType.of(new DataType[] {DataTypes.INT()}, new String[] {"x"})
                },
                new String[] {"metadata", "value", "typed_value"});

buildVariantSchema(physicalType);
// java.lang.ClassCastException: org.apache.paimon.types.IntType cannot be cast to
// org.apache.paimon.types.RowType

What doesn't meet your expectations?

Every other malformed shape in that method raises RuntimeException("Invalid variant shredding schema: " + rowType), which names the schema that was rejected. This one path raises a bare ClassCastException naming two class names and nothing else, so a reader hitting a shredded variant column that Paimon does not recognize gets a stack trace that says nothing about the schema or the column.

I have not produced such a file from another engine, so I am reporting this as the error-reporting defect it is rather than claiming a live read failure. The method is reached with a schema read from the file on every shredded variant read, so the input is not fully under Paimon's control.

Anything else?

Two checks in the same branch are dead and can go at the same time. if (!(dataType instanceof RowType)) sits inside case ROW: of a switch on getTypeRoot(), and RowType is the only type with that root. The other check tests the outer field list for emptiness and duplicates: emptiness is already rejected at the top of the method, and RowType's constructor calls validateFields, which rejects duplicate field names outright, so neither condition can hold by the time that line runs.

Are you willing to submit a PR?

  • I'm willing to submit a PR!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions