{"record":{"id":"7e964416937ec691","repo":"go-sql-driver/mysql","slug":"commands-out-of-sync-you-can-t-run-this-command-n","errorCode":null,"errorMessage":"commands out of sync. You can't run this command now","messagePattern":"commands out of sync\\. You can't run this command now","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"errors.go","lineNumber":27,"sourceCode":"package mysql\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n)\n\n// Various errors the driver might return. Can change between driver versions.\nvar (\n\tErrInvalidConn       = errors.New(\"invalid connection\")\n\tErrMalformPkt        = errors.New(\"malformed packet\")\n\tErrNoTLS             = errors.New(\"TLS requested but server does not support TLS\")\n\tErrCleartextPassword = errors.New(\"this user requires clear text authentication. If you still want to use it, please add 'allowCleartextPasswords=1' to your DSN\")\n\tErrNativePassword    = errors.New(\"this user requires mysql native password authentication\")\n\tErrOldPassword       = errors.New(\"this user requires old password authentication. If you still want to use it, please add 'allowOldPasswords=1' to your DSN. See also https://github.com/go-sql-driver/mysql/wiki/old_passwords\")\n\tErrUnknownPlugin     = errors.New(\"this authentication plugin is not supported\")\n\tErrOldProtocol       = errors.New(\"MySQL server does not support required protocol 41+\")\n\tErrPktSync           = errors.New(\"commands out of sync. You can't run this command now\")\n\tErrPktSyncMul        = errors.New(\"commands out of sync. Did you run multiple statements at once?\")\n\tErrPktTooLarge       = errors.New(\"packet for query is too large. Try adjusting the `Config.MaxAllowedPacket`\")\n\tErrBusyBuffer        = errors.New(\"busy buffer\")\n\n\t// errBadConnNoWrite is used for connection errors where nothing was sent to the database yet.\n\t// If this happens first in a function starting a database interaction, it should be replaced by driver.ErrBadConn\n\t// to trigger a resend. Use mc.markBadConn(err) to do this.\n\t// See https://github.com/go-sql-driver/mysql/pull/302\n\terrBadConnNoWrite = errors.New(\"bad connection\")\n)\n\nvar defaultLogger = Logger(log.New(os.Stderr, \"[mysql] \", log.Ldate|log.Ltime))\n\n// Logger is used to log critical error messages.\ntype Logger interface {\n\tPrint(v ...any)\n}","sourceCodeStart":9,"sourceCodeEnd":45,"githubUrl":"https://github.com/go-sql-driver/mysql/blob/03d76c7e07908e255ce62d126d07ede3f2365d86/errors.go#L9-L45","documentation":"ErrPktSync is returned from readPacket (packets.go:115) when a regular packet's sequence number does not match the expected value and the payload is not an error packet. Sequence numbers track request/response pairing, so a mismatch means the connection's command stream has been corrupted — typically by concurrent use of one connection or by issuing a new command before draining the previous result set.","triggerScenarios":"Using a single *sql.Conn / raw connection from multiple goroutines without serialization; calling Query and starting another Exec before fully iterating the returned *sql.Rows; interleaving a ping with an in-flight result read on a shared connection.","commonSituations":"Sharing a *sql.Conn across goroutines (the *sql.DB pool is safe, a single Conn is not); forgetting rows.Close()/rows.Next() exhaustion before the next statement; driver-level misuse wrapped behind a custom connection manager.","solutions":["Always fully consume or Close() a *sql.Rows before issuing any other command on the same connection.","Do not share a single *sql.Conn between goroutines; use *sql.DB (which pools) or serialize access with a mutex.","If you need exclusive use, use db.Conn(ctx) and release it only after the result set is drained.","Treat the connection as poisoned after this error and let the pool discard it."],"exampleFix":"// before: start a new query while rows still open on same conn\nrows, _ := db.Query(\"SELECT ...\")\ndb.Exec(\"UPDATE ...\") // rows not drained -> ErrPktSync\nrows.Close()\n\n// after: drain (or close) rows first\nrows, _ := db.Query(\"SELECT ...\")\nfor rows.Next() { /* ... */ }\nrows.Close() // connection returned cleanly\ndb.Exec(\"UPDATE ...\")","handlingStrategy":"validation","validationCode":"// Enforce a single-writer-per-conn invariant in your data layer.\ntype lockedConn struct {\n    conn *sql.Conn\n    mu   sync.Mutex\n}\nfunc (lc *lockedConn) exec(ctx context.Context, q string, args ...any) error {\n    lc.mu.Lock()\n    defer lc.mu.Unlock()\n    _, err := lc.conn.ExecContext(ctx, q, args...)\n    return err\n}","typeGuard":"func isPktSync(err error) bool {\n    return errors.Is(err, mysql.ErrPktSync)\n}","tryCatchPattern":"if errors.Is(err, mysql.ErrPktSync) {\n    // connection stream is desynced and poisoned: abandon this conn,\n    // fix the concurrent/un-drained access pattern, then retry.\n}","preventionTips":["Always Close() or fully iterate *sql.Rows before the next statement.","Never share a single *sql.Conn across goroutines; use *sql.DB for concurrency.","Defer rows.Close() immediately after Query.","After any packet-sync error, discard the connection rather than reusing it."],"tags":["protocol","concurrency","rows"],"backgroundTag":null,"analyzedSha":"03d76c7e07908e255ce62d126d07ede3f2365d86","analyzedAt":"2026-08-07T10:39:17.340Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}