fix: serialize null as kdb+ generic null (::) instead of throwing NPE - #106
Merged
sshanks-kx merged 2 commits intoJul 30, 2026
Merged
Conversation
A general list received from kdb+ can contain the generic null :: which
deserializes to a Java null (e.g. `(1;::;3)` -> Object[]{1L, null, 3L}).
Serializing such a list back — or any Object containing null — threw a bare
NullPointerException from n()/Array.getLength(null), so kdb+ data containing
:: could not be round-tripped.
Serialize a null Object as the kdb+ generic null :: (type 101 followed by a 0
byte), the exact inverse of how it is deserialized, and account for it as 2
bytes in nx(). Add a round-trip unit test for a bare null and for a general
list containing a null element.
sshanks-kx
requested changes
Jul 30, 2026
| w((byte)0); | ||
| return; | ||
| } | ||
| int type=t(x); |
Collaborator
There was a problem hiding this comment.
method 't' is for the type number of the object, so checking null and returning type number 101 should prob be in there. will also allow the subsequent line to w the type number, rather than having it twice. the the type 101 can be checked as per other types.
Contributor
Author
There was a problem hiding this comment.
Good call, thanks. Moved the null check into t() (returns type number 101 for the generic null ::), so w/nx now handle it through the normal type dispatch and the type byte is written once. The serialized bytes are unchanged. Pushed in 6d81e0b.
Address review feedback on PR KxSystems#106: instead of special-casing null in w() and nx(), t(null) now returns the generic-null type number 101, so :: is written through the normal type dispatch and the type byte is emitted once. No change to the serialized bytes; adds a t(null)==101 assertion.
sshanks-kx
approved these changes
Jul 30, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
A general list received from kdb+ can contain the generic null
::, which this client deserializes to a Javanull(e.g.(1;::;3)→Object[]{1L, null, 3L}). Serializing such a list back — or anyObjectthat isnull— threw a bareNullPointerException(fromn()→Array.getLength(null)), so kdb+ data containing::could not be round-tripped.Reproduction
Change
Serialize a
nullObjectas the kdb+ generic null::(type101followed by a0byte) — the exact inverse of how it is deserialized — and account for it as 2 bytes innx(). Anullinside a typed array (e.g.String[]) is unaffected and still serializes as that type's null.Testing
Added
testSerializeDeserializeGenericNull, round-tripping a barenulland a general list containing anullelement. Full suite green (85 tests, no regressions).