vitessio/vitess · error

--batch-size only allowed when all queries are CREATE TABLE|

Error message

--batch-size only allowed when all queries are CREATE TABLE|VIEW

What it means

Batching in schemamanager works by concatenating multiple statements into a single migration, which is only supported for CREATE TABLE / CREATE VIEW statements. Execute parses all SQLs and, if any statement is not a CREATE TABLE or CREATE VIEW, returns this error before doing any work.

Source

Thrown at go/vt/schemamanager/tablet_executor.go:477

			}(result)
		}
		wg.Wait()
	}()

	if exec.batchSize > 1 {
		// Before we proceed to batch, we need to validate there's no conflicts.
		if !exec.isDirectStrategy() {
			return errorExecResult(errors.New("--batch-size requires 'direct' ddl_strategy"))
		}
		if exec.hasProvidedUUIDs() {
			return errorExecResult(errors.New("--batch-size conflicts with --uuid-list. Batching does not support UUIDs."))
		}
		allSQLsAreCreate, err := allSQLsAreCreateQueries(sqls, exec.parser)
		if err != nil {
			return errorExecResult(err)
		}
		if !allSQLsAreCreate {
			return errorExecResult(errors.New("--batch-size only allowed when all queries are CREATE TABLE|VIEW"))
		}

		sqls = batchSQLs(sqls, int(exec.batchSize))
	}
	for index, sql := range sqls {
		// Attempt to renew lease:
		if err := rl.Do(func() error { return topo.CheckKeyspaceLocked(ctx, exec.keyspace) }); err != nil {
			return errorExecResult(vterrors.Wrapf(err, "CheckKeyspaceLocked in ApplySchemaKeyspace %v", exec.keyspace))
		}
		execResult.CurSQLIndex = index
		if exec.hasProvidedUUIDs() {
			providedUUID = exec.uuids[index]
		}
		executedAsynchronously, err := exec.executeSQL(ctx, sql, providedUUID, &execResult)
		if err != nil {
			return errorExecResult(err)
		}
		if !executedAsynchronously {

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Ensure every statement in the input is CREATE TABLE or CREATE VIEW when batching
  2. Remove --batch-size and let each non-CREATE statement run as an individual migration
  3. Split the file: batch the CREATEs, run the ALTERs/DROPs unbatched

Example fix

// before
--batch-size 4 with: ALTER TABLE t1 ADD COLUMN c INT; CREATE TABLE t2(...)
// after
--batch-size 4 with only: CREATE TABLE t2(...); CREATE TABLE t3(...)
Defensive patterns

Strategy: validation

Validate before calling

for _, stmt := range sqls {
    up := strings.ToUpper(strings.TrimSpace(stmt))
    if !strings.HasPrefix(up, "CREATE TABLE") && !strings.HasPrefix(up, "CREATE VIEW") {
        return fmt.Errorf("batch-size unsupported statement: %s", stmt)
    }
}

Try / catch

if err != nil && strings.Contains(err.Error(), "only allowed when all queries are CREATE") {
    // re-run with batch-size removed so each statement runs individually
}

Prevention

When it happens

Trigger: Execute called with --batch-size > 1 where the SQL list contains ALTER/DROP/RENAME/INSERT or otherwise non-CREATE statements (allSQLsAreCreateQueries returns false), or where parsing a statement fails (the parse error is returned instead).

Common situations: Feeding a mixed migration file (ALTERs plus CREATEs) to batch mode; assuming batch-size works like a plain statement-grouping option for all DDL.

Related errors


AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01). Data as JSON: /api/errors/5c1d1f5a6f744d64. Report an issue: GitHub.