HA: ClassCastException 'RaftReplicatedDatabase cannot be cast to LocalDatabase' on leader during import / read-only property write (original) (raw)

Summary

Customer (running 3-node Raft HA on Kubernetes) sees the following at runtime on the leader pod during database import:

class com.arcadedb.server.ha.raft.RaftReplicatedDatabase cannot be cast to class com.arcadedb.database.LocalDatabase

This is a real bug in engine code that performs a hard cast to LocalDatabase against the database reference exposed to documents and types. When HA is enabled, that reference is the RaftReplicatedDatabase wrapper, and the cast fails. Without HA the cast succeeds because there is no wrapper, which is why the same code path works in single-node mode.

Affected versions

Confirmed call sites

These are the spots in production code that cast directly to LocalDatabase instead of going through getEmbedded() / getWrappedDatabaseInstance():

  1. engine/src/main/java/com/arcadedb/database/DocumentValidator.java:80 - read-only property validation:
    final Document originalDocument = ((LocalDatabase) document.getDatabase()).getOriginalDocument(document);
    Hit whenever a MutableDocument.save() runs and the type has at least one readonly property and the document is dirty + already persisted. The customer's import workload is the trigger.
  2. engine/src/main/java/com/arcadedb/schema/LocalDocumentType.java:1246 - external-property bucket creation:
    final String overridePath = ((LocalDatabase) schema.getDatabase()).resolveExternalBucketPath();
  3. engine/src/main/java/com/arcadedb/schema/LocalDocumentType.java:1289 - reclaimEmptyExternalBuckets() precondition:
    if (((LocalDatabase) schema.getDatabase()).isTransactionActive())

There may be more in modules I haven't searched (gremlin, graphql, etc.); a global review for (LocalDatabase) against any database reference that can be HA-wrapped is part of the fix.

Proposed fix

Route the cast through the wrapper:

The test fixture RaftReplication3NodesIT already shows the pattern: get ServerDatabase, call .getWrappedDatabaseInstance(), then cast.

Reproduction

  1. Start a 3-node Raft HA cluster (any 26.x build with the Raft plugin).
  2. Define a type with at least one readonly property: CREATE PROPERTY MyType.id STRING (READONLY TRUE).
  3. From the leader pod, insert a record, commit, then update any other field on the same record.
  4. The save fails with the ClassCastException above.

A minimal failing test would create the schema in a 3-node HA setup and update an existing record with a read-only property present.

Customer impact

Tracked alongside #4083 (HA leader-churn resilience and replica health visibility, fixed in commit 203acdaac). This bug is independent (it is a wrapping / casting problem in the engine, not a Raft replication problem), but customers usually trigger both at once during HA import workloads.