diff --git a/nodejs/__test__/arrow.test.ts b/nodejs/__test__/arrow.test.ts index e0859c754..64228e870 100644 --- a/nodejs/__test__/arrow.test.ts +++ b/nodejs/__test__/arrow.test.ts @@ -527,6 +527,19 @@ describe.each([arrow15, arrow16, arrow17, arrow18])( ).toEqual(nestedRecords.map((record) => record.items)); }); + it("will reject incompatible deferred evidence within a list", function () { + for (const items of [ + [[], 1], + [1, []], + [[null], 1], + [1, [null]], + ]) { + expect(() => makeArrowTable([{ items }])).toThrow( + "Failed to infer data type for field items at row 0.", + ); + } + }); + it("will reject empty fixed-size lists", function () { expect(() => makeArrowTable([{ vector: [1, 2, 3] }, { vector: [] }]), diff --git a/nodejs/lancedb/arrow.ts b/nodejs/lancedb/arrow.ts index e939efea3..d3e1e0884 100644 --- a/nodejs/lancedb/arrow.ts +++ b/nodejs/lancedb/arrow.ts @@ -857,12 +857,14 @@ function inferType( ); } let valueType: DataType | undefined; + const deferredItems: unknown[] = []; for (const item of value) { const itemType = inferType(item, path, opts); if (itemType === undefined) { if (!hasOnlyNoTypeEvidence(item)) { return undefined; } + deferredItems.push(item); } else if (valueType === undefined) { valueType = itemType; } else if (!compareInferredTypes(valueType, itemType)) { @@ -872,6 +874,11 @@ function inferType( if (valueType === undefined) { return undefined; } + for (const item of deferredItems) { + if (!noTypeEvidenceMatchesType(item, valueType)) { + return undefined; + } + } // Try to automatically detect embedding columns. if (nameSuggestsVectorColumn(path[path.length - 1])) { // Check if value is a Uint8Array for integer vector type determination