apache/iceberg · error

Invalid default value for %s: %s (must be null)

Error message

Invalid default value for %s: %s (must be null)

What it means

Thrown by Types.NestedField's castDefault when a non-null initialDefault or writeDefault is supplied for a nested-typed field (struct, list, map, variant). Defaults for nested types must be null; only primitive-typed fields accept non-null literal defaults.

Source

Thrown at api/src/main/java/org/apache/iceberg/types/Types.java:897

        Literal<?> writeDefault) {
      Preconditions.checkNotNull(name, "Name cannot be null");
      Preconditions.checkNotNull(type, "Type cannot be null");
      Preconditions.checkArgument(
          isOptional || !type.equals(UnknownType.get()),
          "Cannot create required field with unknown type: %s",
          name);
      this.isOptional = isOptional;
      this.id = id;
      this.name = name;
      this.type = type;
      this.doc = doc;
      this.initialDefault = castDefault(initialDefault, type);
      this.writeDefault = castDefault(writeDefault, type);
    }

    private static Literal<?> castDefault(Literal<?> defaultValue, Type type) {
      if (type.isNestedType() && defaultValue != null) {
        throw new IllegalArgumentException(
            String.format("Invalid default value for %s: %s (must be null)", type, defaultValue));
      } else if (defaultValue != null) {
        Literal<?> typedDefault = defaultValue.to(type);
        Preconditions.checkArgument(
            typedDefault != null, "Cannot cast default value to %s: %s", type, defaultValue);
        return typedDefault;
      }

      return null;
    }

    public boolean isOptional() {
      return isOptional;
    }

    public NestedField asOptional() {
      if (isOptional) {
        return this;

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Pass null (or omit withInitialDefault/withWriteDefault) for fields whose type is nested
  2. Only set literal defaults when the field type is a primitive type
  3. Add a check in schema-building code: if (fieldType.isNestedType()) skip setting the default

Example fix

// before
Types.NestedField.optional(1, "items", Types.ListType.ofOptional(2, Types.StringType.get()))
    .withInitialDefault(literal("x"))
// after
Types.NestedField.optional(1, "items", Types.ListType.ofOptional(2, Types.StringType.get()))
Defensive patterns

Strategy: validation

Validate before calling

if (fieldType.isNestedType() && initialDefault != null) {
  throw new IllegalArgumentException("Defaults must be null for nested type: " + fieldType);
}

Try / catch

try {
  builder.withInitialDefault(literal);
} catch (IllegalArgumentException e) {
  // nested type: retry without a default
}

Prevention

When it happens

Trigger: Building a NestedField with Types.NestedField.required/optional(...).withInitialDefault(someLiteral) (or withWriteDefault) where the field's type is a nested type and the literal is non-null.

Common situations: Programmatic schema builders that blanket-apply defaults to all fields; schema evolution code copying defaults from a primitive field template to nested fields; DDL translation where source engines allow nested defaults but Iceberg does not.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12). Data as JSON: /api/errors/cefb86025c2677e0. Report an issue: GitHub.