micro/go-micro · error

failed to prepare write statement

Error message

failed to prepare write statement

What it means

initDB prepares the INSERT ... ON DUPLICATE KEY UPDATE statement used by sqlStore.Write; a Prepare error means the write path is unusable and configuration fails immediately rather than failing lazily on first Write.

Source

Thrown at store/mysql/mysql.go:171

	// Create a table for the namespace's prefix
	createSQL := fmt.Sprintf("CREATE TABLE IF NOT EXISTS %s (`key` varchar(255) primary key, value blob null, expiry timestamp not null);", s.table)
	_, err = s.db.Exec(createSQL)
	if err != nil {
		return errors.Wrap(err, "Couldn't create table")
	}

	// prepare statements
	var prepareErr error

	s.readPrepare, prepareErr = s.db.Prepare(fmt.Sprintf("SELECT `key`, value, expiry FROM %s.%s WHERE `key` = ?;", s.database, s.table))
	if prepareErr != nil {
		return errors.Wrap(prepareErr, "failed to prepare read statement")
	}

	s.writePrepare, prepareErr = s.db.Prepare(fmt.Sprintf("INSERT INTO %s.%s (`key`, value, expiry) VALUES(?, ?, ?) ON DUPLICATE KEY UPDATE `value`= ?, `expiry` = ?", s.database, s.table))
	if prepareErr != nil {
		return errors.Wrap(prepareErr, "failed to prepare write statement")
	}

	s.deletePrepare, prepareErr = s.db.Prepare(fmt.Sprintf("DELETE FROM %s.%s WHERE `key` = ?;", s.database, s.table))
	if prepareErr != nil {
		return errors.Wrap(prepareErr, "failed to prepare delete statement")
	}

	return nil
}

func (s *sqlStore) configure() error {
	nodes := s.options.Nodes
	if len(nodes) == 0 {
		nodes = []string{"localhost:3306"}
	}

	database := s.options.Database
	if len(database) == 0 {

View on GitHub (pinned to 24529f1404)

Solutions

  1. Read the wrapped cause to distinguish connection vs syntax errors
  2. Ensure the namespace/table produce valid SQL identifiers
  3. Reconnect/retry configure; check MySQL server and proxy health
  4. If the proxy forbids prepared statements, switch to a store backend without them
Defensive patterns

Strategy: retry

Validate before calling

if err := db.Ping(); err != nil {
    return fmt.Errorf("mysql unreachable before store configure: %w", err)
}

Try / catch

if err := st.Init(opts...); err != nil {
    if strings.Contains(err.Error(), "failed to prepare write statement") {
        time.Sleep(time.Second)
        return st.Init(opts...)
    }
    return err
}

Prevention

When it happens

Trigger: configure() -> initDB() calls s.db.Prepare with the upsert SQL and the MySQL driver/server rejects it — broken connection, invalid `<db>.<table>` identifiers, or server refusing PREPARE.

Common situations: Flaky MySQL connectivity during startup; bad namespace chars breaking the interpolated SQL; older MySQL versions or proxies (e.g. some managed tiers) restricting prepared statements.

Related errors


AI-assisted analysis of micro/go-micro@24529f1404 (2026-09-01). Data as JSON: /api/errors/dd029eef8e81e3d4. Report an issue: GitHub.