apache/iceberg · error · java.lang.IllegalArgumentException

Cannot find width for transform: <transform.describe()>

Error message

Cannot find width for transform: <transform.describe()>

What it means

findWidth extracts the width parameter (N for truncate) from a Spark truncate transform's literal argument. If the transform's parameters do not contain an integer Literal of the expected shape, it throws IllegalArgumentException because no width can be determined for the truncate spec.

Source

Thrown at spark/v4.2/spark/src/main/java/org/apache/iceberg/spark/Spark3Util.java:504

          Preconditions.checkArgument(
              lit.value() > 0, "Unsupported width for transform: %s", transform.describe());
          return lit.value();

        } else if (((Literal) expr).dataType() instanceof LongType) {
          Literal<Long> lit = (Literal<Long>) expr;
          Preconditions.checkArgument(
              lit.value() > 0 && lit.value() < Integer.MAX_VALUE,
              "Unsupported width for transform: %s",
              transform.describe());
          if (lit.value() > Integer.MAX_VALUE) {
            throw new IllegalArgumentException();
          }
          return lit.value().intValue();
        }
      }
    }

    throw new IllegalArgumentException("Cannot find width for transform: " + transform.describe());
  }

  private static String leafName(String[] fieldNames) {
    Preconditions.checkArgument(
        fieldNames.length > 0, "Invalid field name: at least one name is required");
    return fieldNames[fieldNames.length - 1];
  }

  private static String peerName(String[] fieldNames, String fieldName) {
    if (fieldNames.length > 1) {
      String[] peerNames = Arrays.copyOf(fieldNames, fieldNames.length);
      peerNames[fieldNames.length - 1] = fieldName;
      return DOT.join(peerNames);
    }
    return fieldName;
  }

  private static String parentName(String[] fieldNames) {

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Provide a constant integer width: truncate(W, col) with W a literal integer
  2. Replace non-literal width expressions with their computed constant value in the DDL
  3. Validate the transform's parameters before conversion

Example fix

// before
PARTITIONED BY (truncate(width_col, data));
// after
PARTITIONED BY (truncate(10, data));
Defensive patterns

Strategy: validation

Validate before calling

// ensure the truncate transform's width is a literal integer before conversion
Object[] params = transform.parameters();
if (params.length == 0 || !(params[0] instanceof Literal)
    || !(((Literal<?>) params[0]).value() instanceof Integer)) {
  throw new IllegalArgumentException("truncate requires a constant integer width");
}

Try / catch

try {
  Spark3Util.toPartitionSpec(schema, transforms);
} catch (IllegalArgumentException e) {
  if (e.getMessage().startsWith("Cannot find width")) {
    // prompt user to supply a constant width
  }
}

Prevention

When it happens

Trigger: A truncate transform whose parameter is missing, non-literal, or not an integer literal (e.g. truncate(noW, col) or a non-constant expression) reaching findWidth via toPartitionSpec or sort conversion.

Common situations: Non-constant width expressions in DDL (variables/functions); typos or wrong argument order in truncate(); SQL generators emitting symbolic widths.

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/ab32a3a7a4f21d19. Report an issue: GitHub.