Skip to content

Problem with reading _rt table in AWS Athena: GENERIC_INTERNAL_ERROR: class org.apache.hadoop.io.Text cannot be cast to class org.apache.hadoop.io.BooleanWritable

0

Currently, I am using the spark hudi deltastreamer job to read CSV and write to the hudi table. Additionally, sync the s3 bucket with the AWS glue catalog. Deltastreamer job creates 2 tables _ro(read-optimized) and _rt(real-time). I wasn't faced with any problem when reading from _ro table. However, I had a problem when selecting a statement in the *_rt table SELECT * FROM "AwsDataCatalog"."database"."table_rt" limit 10;

  • GENERIC_INTERNAL_ERROR: class org.apache.hadoop.io.Text cannot be cast to class org.apache.hadoop.io.BooleanWritable (org.apache.hadoop.io.Text and org.apache.hadoop.io.BooleanWritable are in unnamed module of loader io.trino.server.PluginClassLoader
  • GENERIC_INTERNAL_ERROR: Cannot inspect org.apache.hadoop.hive.serde2.io.DateWritableV2
  • GENERIC_INTERNAL_ERROR: class org.apache.hadoop.io.Text cannot be cast to class org.apache.hadoop.io.IntWritable (org.apache.hadoop.io.Text and org.apache.hadoop.io.IntWritable are in unnamed module of loader io.trino.server.PluginClassLoader @1095de0b) I used the config with hudi deltastreamer:
apiVersion: "sparkoperator.k8s.io/v1beta2"
kind: SparkApplication
metadata:
  generateName: >-
    spark-deltastreamer-
  namespace: spark
spec:
  type: Scala
  mode: cluster
  image: "111111111111.dkr.ecr.us-east-1.amazonaws.com/example-project:{{ .Values.image.tag }}"
  imagePullPolicy: Always
  mainClass: org.apache.hudi.utilities.streamer.HoodieStreamer
  mainApplicationFile: "local:///opt/spark/jars/app.jar"
  sparkConf:
    spark.ui.port: "8090"
    spark.eventLog.enabled: "true"
    spark.eventLog.rolling.enabled: "true"
    spark.eventLog.rolling.maxFileSize: 128m
    spark.hadoop.fs.s3a.path.style.access: "true"
    spark.hadoop.fs.s3a.impl: "org.apache.hadoop.fs.s3a.S3AFileSystem"
    spark.hadoop.fs.s3a.aws.credentials.provider: com.amazonaws.auth.WebIdentityTokenCredentialsProvider
    spark.sql.catalogImplementation: hive
    spark.sql.hive.convertMetastoreParquet: "false"
    spark.sql.extensions: org.apache.spark.sql.hudi.HoodieSparkSessionExtension
    spark.sql.catalog.spark_catalog: org.apache.spark.sql.hudi.catalog.HoodieCatalog
    spark.sql.parquet.mergeSchema: "true"
    spark.hadoop.spark.sql.hive.convertMetastoreParquet: "false"
    spark.hadoop.spark.sql.legacy.parquet.nanosAsLong: "false"
    spark.hadoop.spark.sql.parquet.binaryAsString: "false"
    spark.hadoop.spark.sql.parquet.int96AsTimestamp: "true"
    spark.hadoop.spark.sql.caseSensitive: "false"
  arguments:
    - --target-base-path
    - "s3a://{{`{{inputs.parameters.customer}}`}}.data.{{ .Values.infrastructure }}/tabular/{{`{{inputs.parameters.namespace}}`}}/{{`{{inputs.parameters.targetTable}}`}}"
    - --target-table
    - "{{`{{inputs.parameters.targetTable}}`}}"
    - --table-type
    - "MERGE_ON_READ"
    - --source-class
    - org.apache.hudi.utilities.sources.CsvDFSSource
    - --transformer-class
    - io.example.Transformer
    - --source-ordering-field
    - "ce_timestamp"
    - --hoodie-conf
    - "hoodie.streamer.source.dfs.root=s3a://{{`{{inputs.parameters.customer}}`}}.data.{{ .Values.infrastructure }}/{{`{{inputs.parameters.namespace}}`}}/datamart/{{`{{inputs.parameters.sourceFolder}}`}}"
    - --hoodie-conf
    - "hoodie.table.precombine.field=ce_timestamp"
    - --hoodie-conf
    - "hoodie.datasource.write.recordkey.field=ce_id"
    - --hoodie-conf
    - "hoodie.datasource.write.precombine.field=ce_timestamp"
    - --hoodie-conf
    - "hoodie.datasource.write.partitionpath.field=period"
    - --hoodie-conf
    - "hoodie.datasource.write.table.type=MERGE_ON_READ"
    - --hoodie-conf
    - "hoodie.datasource.write.table.name={{`{{inputs.parameters.targetTable}}`}}"
    - --hoodie-conf
    - "hoodie.datasource.write.hive_style_partitioning=true"
    - --hoodie-conf
    - "hoodie.deltastreamer.csv.sep=,"
    - --hoodie-conf
    - "hoodie.deltastreamer.csv.quote=\""
    - --hoodie-conf
    - "hoodie.deltastreamer.csv.escape=\""
    - --hoodie-conf
    - "hoodie.deltastreamer.csv.header=true"
    - --hoodie-conf
    - "hoodie.datasource.write.operation=bulk_insert"
    - --hoodie-conf
    - "hoodie.avro.schema.validate=true"
    - --hoodie-conf
    - "hoodie.avro.schema.validate.enable=true"
    - --sync-tool-classes
    - org.apache.hudi.aws.sync.AwsGlueCatalogSyncTool
    - --enable-sync
    - --hoodie-conf
    - "hoodie.datasource.hive_sync.database={{ .Values.infrastructure }}_{{`{{inputs.parameters.namespace}}`}}_{{`{{inputs.parameters.customer}}`}}"
    - --hoodie-conf
    - "hoodie.datasource.hive_sync.table={{`{{inputs.parameters.targetTable}}`}}"
    - --hoodie-conf
    - "hoodie.datasource.hive_sync.enable=true"
    - --hoodie-conf
    - "hoodie.datasource.hive_sync.auto_create_database=true"
    - --hoodie-conf
    - "hoodie.datasource.hive_sync.support_timestamp=true"
    - --schemaprovider-class
    - org.apache.hudi.utilities.schema.FilebasedSchemaProvider
    - --hoodie-conf
    - "hoodie.streamer.schemaprovider.source.schema.file=/opt/spark/schemas/source/{{`{{inputs.parameters.sourceFolder}}`}}-schema.avsc"
    - --hoodie-conf
    - "hoodie.streamer.schemaprovider.target.schema.file=/opt/spark/schemas/target/{{`{{inputs.parameters.sourceFolder}}`}}-schema.avsc"

asked 2 years ago543 views

1 Answer
0

Hi Pavlo, thanks for sharing your question to re:Post.

Issue

In looking at the error message you shared, when querying a Hudi Merge-on-Read (MoR) real-time table (_rt) in Athena, you encountered type casting errors:

GENERIC_INTERNAL_ERROR: class org.apache.hadoop.io.Text cannot be cast to class org.apache.hadoop.io.BooleanWritable
GENERIC_INTERNAL_ERROR: Cannot inspect org.apache.hadoop.hive.serde2.io.DateWritableV2
GENERIC_INTERNAL_ERROR: class org.apache.hadoop.io.Text cannot be cast to class org.apache.hadoop.io.IntWritable

The _ro (read-optimized) table queries successfully, but the _rt (real-time) table fails.


Specific Diagnosis from Your Errors

Based on your error messages:

Your data has columns stored as TEXT/STRING in the Avro delta files, but the Glue Catalog schema defines them as:

  • Boolean - Error: Text cannot be cast to BooleanWritable
  • Integer - Error: Text cannot be cast to IntWritable
  • Date - Error: Cannot inspect DateWritableV2

Why _ro works but _rt fails:

  • _ro table: Reads only Parquet base files (which may have correct types)
  • _rt table: Merges Parquet base files + Avro delta files (where types are strings)

Root cause: When your Deltastreamer reads CSV files, string values are being written to Avro delta files as TEXT instead of being converted to the proper data types (boolean, int, date) defined in your Avro schema.

This typically happens when:

  1. Your Avro schema defines fields as string instead of proper types
  2. CSV values aren't being cast to the correct types during ingestion
  3. Schema validation isn't catching the mismatch

Root Cause

This error occurs due to schema mismatch or data type inconsistencies between:

  1. The table schema registered in AWS Glue Data Catalog
  2. The actual data types in the Parquet (base) and Avro (delta) files
  3. How Athena interprets these types when querying MoR real-time tables

Hudi MoR tables store data in two formats:

  • Base files: Parquet (columnar)
  • Delta/log files: Avro (row-based)

When querying _rt tables, Athena must merge both formats. Type mismatches between the Glue schema and actual file data cause these casting errors.

Reference: Query Apache Hudi datasets


Common Causes

1. Schema Evolution Issues

Your Avro schema files may not match the actual data types in your CSV source or the Glue Catalog schema.

2. Hive Sync Configuration

The AwsGlueCatalogSyncTool may have registered incorrect data types in the Glue Catalog.

3. Spark Configuration Mismatches

Spark configurations for type handling may conflict with how Athena reads the data:

  • spark.sql.parquet.int96AsTimestamp
  • spark.sql.legacy.parquet.nanosAsLong
  • spark.sql.parquet.binaryAsString

4. CSV to Avro Type Inference

When reading CSV files, Spark may infer types differently than what's defined in your Avro schema.


Solutions

Solution 1: Fix Your Avro Schema Files (Most Likely Fix)

This is likely your main issue. Check your Avro schema files at:

  • /opt/spark/schemas/source/<sourceFolder>-schema.avsc
  • /opt/spark/schemas/target/<sourceFolder>-schema.avsc

Your schemas might look like this:

{
  "type": "record",
  "name": "YourTable",
  "fields": [
    {"name": "boolean_field", "type": ["null", "string"]},  // ❌ Should be boolean
    {"name": "int_field", "type": ["null", "string"]},      // ❌ Should be int
    {"name": "date_field", "type": ["null", "string"]},     // ❌ Should be date
    {"name": "string_field", "type": ["null", "string"]}    // ✓ Correct
  ]
}

Change them to this, for example:

{
  "type": "record",
  "name": "YourTable",
  "fields": [
    {"name": "boolean_field", "type": ["null", "boolean"]},
    {"name": "int_field", "type": ["null", "int"]},
    {"name": "date_field", "type": ["null", {"type": "int", "logicalType": "date"}]},
    {"name": "string_field", "type": ["null", "string"]}
  ]
}

Check that:

  • Boolean fields are defined as boolean, not string
  • Integer fields are defined as int or long, not string
  • Date fields use proper logical types

Reference: Apache Avro Specification


Solution 2: Update Glue Catalog Schema

The Glue Catalog schema may be incorrect. Update it manually or re-sync:

  1. Check current schema in Glue Console:

    • Navigate to AWS Glue > Tables
    • Find your table_rt table
    • Review column data types
  2. Update schema if needed:

    aws glue update-table --database-name <database> \
      --table-input '{
        "Name": "table_rt",
        "StorageDescriptor": {
          "Columns": [
            {"Name": "boolean_field", "Type": "boolean"},
            {"Name": "int_field", "Type": "int"},
            {"Name": "date_field", "Type": "date"}
          ]
        }
      }'
  3. Or drop and re-sync the table:

    • Delete the _rt table from Glue Catalog
    • Re-run your Deltastreamer job to re-sync

Reference: AWS Glue Data Catalog


Solution 3: Add Schema Validation in Deltastreamer

Update your Deltastreamer configuration to enforce strict schema validation:

- --hoodie-conf
- "hoodie.avro.schema.validate=true"
- --hoodie-conf
- "hoodie.avro.schema.validate.enable=true"
- --hoodie-conf
- "hoodie.datasource.write.schema.allow.auto.evolution.column.drop=false"

You already have validation enabled, but ensure your source and target schemas are identical.


Solution 4: Use Explicit Type Casting in CSV Reading

Modify your Spark configuration to explicitly define CSV column types instead of relying on inference:

sparkConf:
  spark.sql.csv.inferSchema: "false"

Then define the schema explicitly in your transformer or use a schema file that matches your Avro schema exactly.


Solution 5: Query _ro Table Instead

As a temporary workaround, query the read-optimized (_ro) table instead of the real-time (_rt) table:

SELECT * FROM "AwsDataCatalog"."database"."table_ro" LIMIT 10;

Trade-off: The _ro table shows only compacted data and may not include the most recent updates until compaction runs.

Reference: Hudi Query Types


Solution 6: Check for Null Handling

Ensure your Avro schema properly handles nullable fields using union types:

{"name": "field_name", "type": ["null", "int"]}

Not:

{"name": "field_name", "type": "int"}

Debugging Steps

  1. Compare schemas:

    # Check Glue Catalog schema
    aws glue get-table --database-name <db> --name table_rt
    
    # Check actual Parquet schema
    aws s3 cp s3://bucket/path/to/file.parquet - | parquet-tools schema -
  2. Examine Avro schema files:

    • Review /opt/spark/schemas/source/<folder>-schema.avsc
    • Review /opt/spark/schemas/target/<folder>-schema.avsc
    • Ensure they match your CSV data types
  3. Check Hudi metadata:

    SELECT * FROM "database"."table_rt$timeline" LIMIT 10;
  4. Test with specific columns:

    -- Instead of SELECT *, test individual columns
    SELECT string_column FROM "database"."table_rt" LIMIT 10;
    SELECT int_column FROM "database"."table_rt" LIMIT 10;

    This helps identify which specific column has the type mismatch.


Additional Configuration to Try

Add these Hudi configurations to your Deltastreamer job:

- --hoodie-conf
- "hoodie.datasource.hive_sync.support_timestamp=true"
- --hoodie-conf
- "hoodie.datasource.hive_sync.skip_ro_suffix=false"
- --hoodie-conf
- "hoodie.datasource.hive_sync.skip_rt_sync=false"

References

AWS
EXPERT

answered 9 months ago

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.