golang-migrate/migrate · error

"%s" MigrationsTable contains too many dot characters

Error message

"%s" MigrationsTable contains too many dot characters

What it means

When MigrationsTableQuoted is true, WithConnection parses the quoted MigrationsTable with the regex "(.*?)" and expects at most two captures: schema and table. If more than two quoted segments are present (more than one dot), it returns this error because a Postgres identifier can only be schema.table. The driver cannot unambiguously split the name.

Source

Thrown at database/postgres/postgres.go:116

		}

		config.SchemaName = schemaName.String
	}

	if len(config.MigrationsTable) == 0 {
		config.MigrationsTable = DefaultMigrationsTable
	}

	config.migrationsSchemaName = config.SchemaName
	config.migrationsTableName = config.MigrationsTable
	if config.MigrationsTableQuoted {
		re := regexp.MustCompile(`"(.*?)"`)
		result := re.FindAllStringSubmatch(config.MigrationsTable, -1)
		config.migrationsTableName = result[len(result)-1][1]
		if len(result) == 2 {
			config.migrationsSchemaName = result[0][1]
		} else if len(result) > 2 {
			return nil, fmt.Errorf("\"%s\" MigrationsTable contains too many dot characters", config.MigrationsTable)
		}
	}

	px := &Postgres{
		conn:   conn,
		config: config,
	}

	if err := px.ensureVersionTable(); err != nil {
		return nil, err
	}

	return px, nil
}

func WithInstance(instance *sql.DB, config *Config) (database.Driver, error) {
	ctx := context.Background()

View on GitHub (pinned to 01a9643f14)

Solutions

  1. Reduce MigrationsTable to at most two quoted parts: "schema"."table" (drop the database name — connect to the database instead)
  2. Use just "table" if the schema is the default/current one
  3. Set MigrationsTableQuoted=false and use a simple unquoted name if quoting is unnecessary

Example fix

// before
cfg := &postgres.Config{MigrationsTable: `"mydb"."myschema"."schema_migrations"`, MigrationsTableQuoted: true}
// after
cfg := &postgres.Config{MigrationsTable: `"myschema"."schema_migrations"`, MigrationsTableQuoted: true}
Defensive patterns

Strategy: validation

Validate before calling

if cfg.MigrationsTableQuoted {
    parts := strings.Count(cfg.MigrationsTable, ".")
    if parts > 1 {
        return fmt.Errorf("MigrationsTable %q may have at most schema.table (one dot)", cfg.MigrationsTable)
    }
}

Try / catch

d, err := postgres.WithConnection(conn, cfg)
if err != nil {
    if strings.Contains(err.Error(), "too many dot characters") {
        log.Fatal("quoted MigrationsTable must be \"schema\".\"table\" — drop the database prefix")
    }
    panic(err)
}

Prevention

When it happens

Trigger: Calling postgres.WithConnection (directly or via WithInstance) with Config{MigrationsTableQuoted: true, MigrationsTable: "a"."b"."c"} — i.e. three or more quoted identifiers.

Common situations: Pasting a fully-qualified name with database prefix (db.schema.table) into MigrationsTable; nested quoting mistakes producing extra "..." pairs; misunderstanding that only two levels are valid in Postgres identifiers.

Related errors


AI-assisted analysis of golang-migrate/migrate@01a9643f14 (2026-09-02). Data as JSON: /api/errors/c96c77124b88b270. Report an issue: GitHub.