apache/iceberg · error

cannotCreateViewNotEnoughColumnsError(viewNameParts…

Error message

cannotCreateViewNotEnoughColumnsError(viewNameParts, columns, query)

What it means

When CREATE VIEW specifies an explicit column list, Iceberg's CheckViews validates the column count against the query output. If the declared column list is shorter than the query's output columns, cannotCreateViewNotEnoughColumnsError is thrown, preventing a view whose schema declaration is inconsistent with its definition.

Solutions

  1. Add column names to the view's column list so it matches the query output length
  2. Remove extra output columns from the SELECT (or select only the needed ones)
  3. Drop explicit column names entirely and let the view inherit query output names
  4. Alias the query outputs so the un-declared names are intentional

Example fix

-- before
CREATE VIEW v (id) AS SELECT id, name FROM t;
-- after
CREATE VIEW v (id, name) AS SELECT id, name FROM t;
Defensive patterns

Strategy: validation

Validate before calling

val outputCols = spark.sql(query).schema.length
require(namedColumns.length == outputCols,
  s"view column list (${namedColumns.length}) must match query output ($outputCols)")

Prevention

When it happens

Trigger: `CREATE VIEW v (c1, c2) AS SELECT a, b, c FROM t` — the named column list has fewer entries than the SELECT output; validation happens in CheckViews during analysis of CreateViewStatement.

Common situations: Hand-written CREATE VIEW where someone renamed/added columns to the SELECT but forgot to update the column list; generated SQL templates with fixed column names; refactoring a view's underlying query.

Related errors


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

Appendix: source

Thrown at spark/v4.2/spark-extensions/src/main/scala/org/apache/spark/sql/catalyst/analysis/CheckViews.scala:75

          case _ => // OK
        }

      case AlterViewAs(ResolvedV2View(_, _, _), _, _, _, _) =>
        throw new IcebergAnalysisException(
          "ALTER VIEW <viewName> AS is not supported. Use CREATE OR REPLACE VIEW instead")

      case _ => // OK
    }
  }

  private def verifyColumnCount(
      ident: ResolvedIdentifier,
      columns: Seq[String],
      query: LogicalPlan): Unit = {
    if (columns.nonEmpty) {
      val viewNameParts = ident.catalog.name() +: ident.identifier.asMultipartIdentifier
      if (columns.length > query.output.length) {
        throw QueryCompilationErrors.cannotCreateViewNotEnoughColumnsError(
          viewNameParts,
          columns,
          query)
      } else if (columns.length < query.output.length) {
        throw QueryCompilationErrors.cannotCreateViewTooManyColumnsError(
          viewNameParts,
          columns,
          query)
      }
    }
  }

  // Spark's ViewHelper.checkCyclicViewReference only matches a SubqueryExpression at the root of
  // each expression. Keep a custom traversal so cycles in predicates and other nested expressions
  // are detected.
  private def checkCyclicViewReference(
      viewIdent: Seq[String],
      plan: LogicalPlan,

View on GitHub (pinned to 86d9c8fc54)