Skip to content

Commit cb27492

Browse files
committed
buildEmptyBatch: fix List/Map children → child (singular)
assembleListVector in arrow-js was crashing with 'TypeError: undefined is not an object (evaluating data.children[0].slice)' when serializing zero-row batches whose schema included list columns. Root cause: makeData's overloads for List and Map take `child` (singular) — see arrow-js/src/data.ts visitList/visitMap — but we were passing `children: [childData]` (plural array). Arrow-JS ignored the unknown property and constructed the Data with an empty children array, producing a List Data with no values sub-array. TypeScript didn't catch this because the call was suffixed with `as any`, bypassing property- shape validation entirely. FixedSizeList was already correct (child singular). List and Map were wrong. Passing `child: childData` for both lets IPC serialize 0-row batches with list/map columns through httpDispatchStreamInit's token batch path. Also bumps echo/all_types past the list column cases on HTTP; struct/ map/union cases still surface a separate state-token issue to chase.
1 parent 589a95f commit cb27492

1 file changed

Lines changed: 8 additions & 2 deletions

File tree

src/wire/response.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,19 +143,25 @@ function makeEmptyData(type: DataType): Data {
143143
return makeData({ type, length: 0, children, nullCount: 0 });
144144
}
145145
if (DataType.isList(type)) {
146+
// Arrow-JS's makeData for List expects `child` (singular), not
147+
// `children` — the latter is silently ignored (cast `as any` hides
148+
// the mismatch). Without the correct key Data.children[0] is
149+
// undefined, which blows up VectorAssembler when the zero-row batch
150+
// is serialized into the IPC stream.
146151
const childData = makeEmptyData(type.children[0].type);
147-
return makeData({ type, length: 0, children: [childData], nullCount: 0, valueOffsets: new Int32Array([0]) } as any);
152+
return makeData({ type, length: 0, child: childData, nullCount: 0, valueOffsets: new Int32Array([0]) } as any);
148153
}
149154
if (DataType.isFixedSizeList(type)) {
150155
const childData = makeEmptyData(type.children[0].type);
151156
return makeData({ type, length: 0, child: childData, nullCount: 0 } as any);
152157
}
153158
if (DataType.isMap(type)) {
159+
// Same story as List above: Map's makeData takes `child` (singular).
154160
const entryType = type.children[0]?.type;
155161
const entryData = entryType
156162
? makeEmptyData(entryType)
157163
: makeData({ type: new Struct([]), length: 0, children: [], nullCount: 0 });
158-
return makeData({ type, length: 0, children: [entryData], nullCount: 0, valueOffsets: new Int32Array([0]) } as any);
164+
return makeData({ type, length: 0, child: entryData, nullCount: 0, valueOffsets: new Int32Array([0]) } as any);
159165
}
160166
return makeData({ type, length: 0, nullCount: 0 });
161167
}

0 commit comments

Comments
 (0)