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.

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.

Appendix: 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)