Skip to content

fix: move timezone string creation before startTimestamp to avoid nesting assertion#148

Merged
kou merged 2 commits into
apache:mainfrom
jding-xyz:fix/timestamp-nesting-and-ios
Mar 25, 2026
Merged

fix: move timezone string creation before startTimestamp to avoid nesting assertion#148
kou merged 2 commits into
apache:mainfrom
jding-xyz:fix/timestamp-nesting-and-ios

Conversation

@jding-xyz
Copy link
Copy Markdown
Contributor

@jding-xyz jding-xyz commented Mar 19, 2026

Problem

ArrowWriter.writeStreaming() crashes with a FlatBuffers assertion when writing any schema containing a Timestamp field with a timezone (e.g. timestamp[us, UTC]):

FlatBuffers/FlatBufferBuilder.swift:317: Assertion failed: Object serialization must not be nested

In toFBType() (ArrowWriterHelper.swift), the .timestamp case calls fbb.create(string: timezone) inside the startTimestamp/endTimestamp table context. FlatBuffers' create(string:) calls notNested() which asserts !isNested, but startTimestamp (which calls startTable) has already set isNested = true.

Fix

Move the fbb.create(string:) call before startTimestamp(). This is the standard FlatBuffers pattern: all child objects (strings, vectors, tables) must be created before starting their parent table.

// Before (buggy):
let startOffset = org_apache_arrow_flatbuf_Timestamp.startTimestamp(&fbb)
// ...
if let timezone = timestampType.timezone {
    let timezoneOffset = fbb.create(string: timezone) // ASSERTS
}

// After (fixed):
let timezoneOffset = timestampType.timezone.map { fbb.create(string: $0) }
let startOffset = org_apache_arrow_flatbuf_Timestamp.startTimestamp(&fbb)
// ...
if let offset = timezoneOffset {
    org_apache_arrow_flatbuf_Timestamp.add(timezone: offset, &fbb)
}

Testing

Added testTimestampWithTimezoneInMemoryToFromStream which writes a timestamp[us, UTC] column through writeStreaming and reads it back, verifying the schema (unit, timezone) and data survive the roundtrip. This test would crash with the nesting assertion before the fix.

AI disclosure

The code change and test were written with the assistance of Cursor (AI). I identified the bug by tracing the FlatBuffers assertion through the startTable/notNested call chain, reviewed all generated code, and verified correctness by running the test suite locally.

…ting assertion

FlatBuffers' `create(string:)` calls `notNested()` which asserts
`!isNested`. In the `.timestamp` case of `toFBType()`, the timezone
string was created inside the `startTimestamp`/`endTimestamp` table
context, which has `isNested = true`. This causes a runtime assertion
failure when writing any schema with `Timestamp` that has a timezone
(e.g. `timestamp[us, UTC]`).

The fix moves `fbb.create(string:)` before `startTimestamp()`, which
is the standard FlatBuffers pattern: all child objects (strings,
vectors, tables) must be created before starting their parent table.

Made-with: Cursor
@jding-xyz jding-xyz force-pushed the fix/timestamp-nesting-and-ios branch 3 times, most recently from e8af1c0 to 3923641 Compare March 19, 2026 19:30
@kou
Copy link
Copy Markdown
Member

kou commented Mar 20, 2026

Could you also add a new test for the case?

@kou
Copy link
Copy Markdown
Member

kou commented Mar 20, 2026

@jding-xyz
Copy link
Copy Markdown
Contributor Author

Thanks for the review. I've pushed a test (testTimestampWithTimezoneInMemoryToFromStream) that does a write/read roundtrip with a timestamp[us, UTC] column. This exercises the exact code path that crashed before the fix.

I've read the AI policy. The fix and test were written with AI assistance (Cursor). I identified the issue when try to use this package. AI helped root cause by tracing FlatBuffers' startTable -> isNested = true -> create(string:) -> notNested() assertion chain, and I've reviewed and verified all generated code. I understand the fix and can debug it.

Copy link
Copy Markdown
Member

@kou kou left a comment

Choose a reason for hiding this comment

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

+1

@kou kou merged commit 79521cd into apache:main Mar 25, 2026
6 checks 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