Skip to content

fix: raise clear error for on-disk (splayed) table reference - #104

Merged
sshanks-kx merged 2 commits into
KxSystems:masterfrom
belowzeroff:fix/splayed-table-cce
Jul 31, 2026
Merged

fix: raise clear error for on-disk (splayed) table reference#104
sshanks-kx merged 2 commits into
KxSystems:masterfrom
belowzeroff:fix/splayed-table-cce

Conversation

@belowzeroff

Copy link
Copy Markdown
Contributor

Summary

Deserializing an on-disk (splayed/partitioned) table reference crashes the client with an opaque ClassCastException instead of a meaningful error. This PR turns that into a clear, actionable exception.

Addresses #51.

Reproduction

c conn = new c("localhost", 5001);
conn.k("get `:test/ set ([] a:til 10)");
java.lang.ClassCastException: class java.lang.String cannot be cast to class [Ljava.lang.Object;
    at com.kx.c$Flip.<init>(c.java:640)
    at com.kx.c.r(c.java:1149)
    at com.kx.c.deserialize(c.java:1567)
    ...

Root cause

A splayed table whose columns live on disk is transmitted as table(98) → dict(99) whose value is the on-disk path symbol (`:test/, type -11) rather than the column data. Flip(Dict) unconditionally casts dict.y to Object[], which fails for the symbol atom. The column data is simply not present in the message, so it cannot be reconstructed on the Java side (q itself errors with 'test/a. OS reports: No such file or directory when you index such a table without disk access).

Change

Flip(Dict) now detects when the value is not a list of columns and throws a descriptive IllegalArgumentException naming the referenced path and explaining how to materialize the table in kdb+ before sending it, e.g.:

Cannot create a Flip from a table whose column data is stored on disk
(splayed/partitioned table); kdb+ sent a reference to ":test/" instead of the
column values. Materialize the table in kdb+ before sending it, e.g.
`select from t` or `value flip t`.

This is a minimal, non-breaking change (the previous behaviour was already an unchecked exception, just an opaque one) and leaves normal in-memory tables untouched.

Testing

  • Added testDeserializeSplayedTableReference, built from the exact IPC bytes captured in ClassCastException on reading splay table #51, asserting the clear IllegalArgumentException.
  • Full suite green: 85 tests, 0 failures (84 existing + 1 new), no regressions.

Reading a splayed/partitioned table (e.g. `get `:test/ set ([] a:til 10)`)
crashed the client with an opaque
"ClassCastException: class java.lang.String cannot be cast to class
[Ljava.lang.Object;".

kdb+ transmits such a table as table(98) -> dict(99) whose value is the
on-disk path symbol (`:test/`, type -11) rather than the column data, so the
Flip(Dict) constructor's (Object[]) dict.y cast fails. The column data is not
present in the message and cannot be materialized on the Java side.

Detect this case in Flip(Dict) and throw a descriptive
IllegalArgumentException that names the referenced path and explains how to
materialize the table in kdb+ before sending it. Add a unit test built from
the exact IPC bytes reported in issue KxSystems#51.
Comment thread javakdb/src/main/java/com/kx/c.java Outdated
public Flip(Dict dict){
x=(String[])dict.x;
if(!(dict.y instanceof Object[]))
throw new IllegalArgumentException("Cannot create a Flip from a table whose column data is stored on disk"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although useful in this situation, equally someone could have a bug in their code which could trigger this error (e.g bug in how they constructed a Dict). In which case the explanation in the exception would be confusing and misleading for them.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, thanks — reworded so the message leads with the actual condition (the dictionary values must be an Object[] of columns) and presents both a splayed/on-disk table and a mis-constructed Dict as possible causes, rather than assuming the on-disk case. Also added a test for the plain mis-constructed-Dict path. Pushed in fadbed5.

Address review feedback on PR KxSystems#104: the guard fires whenever the dict values
are not an Object[] of columns, which can also result from a mis-constructed
Dict, not only a splayed/on-disk table. Reword the message to lead with the
actual condition and present both causes, so it does not mislead a caller whose
own code produced the bad Dict. Add a test for the mis-constructed-Dict case.
@sshanks-kx
sshanks-kx merged commit 8efe03f into KxSystems:master Jul 31, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants