lancedb/lancedb · error

Expected a Schema but object was null/undefined

Error message

Expected a Schema but object was null/undefined

What it means

sanitizeSchemaWithContext accepts either a real apache-arrow `Schema` instance (returned as-is) or a schema-like plain object. If the input is not an object at all (null, undefined, a primitive), it cannot be a schema, so this error is thrown immediately. It exists to give a clear message instead of a cryptic `Cannot read properties of null` from the subsequent property checks.

Solutions

  1. Check the value is non-null before calling: `if (!schemaLike) throw ...` or pass a real `Schema` instance.
  2. If the schema came from JSON, parse it (`JSON.parse`) rather than passing the raw string.
  3. If the schema is loaded async, `await` the promise before use.
  4. Construct the schema with `new Schema(fields)` from apache-arrow so it takes the fast path and bypasses sanitization.

Example fix

// before
const t = table.schema.then(s => sanitizeSchema(s))  // schema still undefined here
sanitizeSchema(maybeSchema);
// after
if (maybeSchema == null) throw new Error('schema is required');
const s = await loadSchema();
sanitizeSchema(s);
Defensive patterns

Strategy: type-guard

Validate before calling

if (schemaLike == null || typeof schemaLike !== 'object') {
  throw new Error(`expected a schema object, got ${schemaLike === null ? 'null' : typeof schemaLike}`);
}

Type guard

import { Schema } from 'apache-arrow';
function isSchemaLike(v: unknown): v is Schema | { fields: unknown[] } {
  return v instanceof Schema || (typeof v === 'object' && v !== null);
}

Try / catch

try {
  const schema = sanitizeSchemaWithContext(maybeSchema, ctx);
} catch (e) {
  if (e.message.includes('object was null/undefined')) {
    console.error('Schema was never populated; check async loading and JSON parsing');
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling sanitizeSchema/schema (or table APIs that call parseTableData -> sanitizeTable) with `undefined` because an optional schema variable was never assigned; passing `null` explicitly; passing a non-object such as a string of serialized JSON instead of the parsed object.

Common situations: Loading a schema asynchronously and using it before the promise resolves; a failed JSON.parse silently yielding null and being forwarded; destructuring mistakes passing the wrong variable; IPC handlers receiving `undefined` payloads.

Related errors


AI-assisted analysis of lancedb/lancedb@c7b051aff7 (2026-09-08). Data as JSON: /api/errors/3985ee0751a206a2. Report an issue: GitHub.

Appendix: source

Thrown at nodejs/lancedb/sanitize.ts:627

 * Convert something schemaLike into a Schema instance
 *
 * This method is often needed even when the caller is using a Schema
 * instance because they might be using a different instance of apache-arrow
 * than lancedb is using.
 */
export function sanitizeSchema(schemaLike: SchemaLike): Schema {
  return sanitizeSchemaWithContext(schemaLike, createSanitizationContext());
}

function sanitizeSchemaWithContext(
  schemaLike: SchemaLike,
  context: SanitizationContext,
): Schema {
  if (schemaLike instanceof Schema) {
    return schemaLike;
  }
  if (typeof schemaLike !== "object" || schemaLike === null) {
    throw Error("Expected a Schema but object was null/undefined");
  }
  if (!("fields" in schemaLike)) {
    throw Error(
      "The schema passed in does not appear to be a schema (no 'fields' property)",
    );
  }
  let metadata;
  if ("metadata" in schemaLike) {
    metadata = sanitizeMetadata(schemaLike.metadata);
  }
  if (!Array.isArray(schemaLike.fields)) {
    throw Error(
      "The schema passed in had a 'fields' property but it was not an array",
    );
  }
  const sanitizedFields = schemaLike.fields.map((field) =>
    sanitizeFieldWithContext(field, context),
  );

View on GitHub (pinned to c7b051aff7)