{"record":{"id":"492505617e152d68","repo":"go-sql-driver/mysql","slug":"commands-out-of-sync-did-you-run-multiple-stateme","errorCode":null,"errorMessage":"commands out of sync. Did you run multiple statements at once?","messagePattern":"commands out of sync\\. Did you run multiple statements at once\\?","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"errors.go","lineNumber":28,"sourceCode":"\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}\n","sourceCodeStart":10,"sourceCodeEnd":46,"githubUrl":"https://github.com/go-sql-driver/mysql/blob/03d76c7e07908e255ce62d126d07ede3f2365d86/errors.go#L10-L46","documentation":"ErrPktSyncMul is returned from readPacket (packets.go:74) when a sequence-number mismatch is detected while reassembling a multi-packet (split, payload larger than maxPacketSize) response. It is the large-payload variant of ErrPktSync: the desync happened partway through a >16 MiB result.","triggerScenarios":"Same root causes as ErrPktSync (concurrent use or un-drained result sets) but occurring during the read of a multi-part packet, i.e. a very large row or a result set whose individual packet exceeds 16 MiB.","commonSituations":"Streaming large BLOBs / LOAD DATA results while another goroutine touches the connection; a giant result set read concurrently with a health-check ping.","solutions":["Serialize all access to a single connection; never read a result set and issue another command concurrently.","Fully drain or Close() large result sets before starting the next operation.","Reduce payload sizes (smaller SELECTs, paging) so responses fit in single packets.","Increase the server max_allowed_packet only if genuinely needed; it does not fix concurrency bugs."],"exampleFix":"// before: large SELECT reassembled while another op races on the conn\n//   -> ErrPktSyncMul mid-stream\n\n// after: read the large result to completion on one conn, then proceed\nconn, _ := db.Conn(ctx)\nrows, _ := conn.QueryContext(ctx, \"SELECT big_col FROM t\")\nfor rows.Next() { /* consume entirely */ }\nrows.Close()\nconn.Close()","handlingStrategy":"validation","validationCode":"// For large results, drain them fully on a dedicated conn before doing\n// anything else.\nfunc drainLarge(ctx context.Context, db *sql.DB, q string) error {\n    conn, err := db.Conn(ctx)\n    if err != nil { return err }\n    defer conn.Close()\n    rows, err := conn.QueryContext(ctx, q)\n    if err != nil { return err }\n    defer rows.Close()\n    for rows.Next() { /* consume all */ }\n    return rows.Err()\n}","typeGuard":"func isPktSyncMul(err error) bool {\n    return errors.Is(err, mysql.ErrPktSyncMul)\n}","tryCatchPattern":"if errors.Is(err, mysql.ErrPktSyncMul) {\n    // a multi-packet read desynced: serialize conn access, page the large\n    // result, and retry on a fresh connection.\n}","preventionTips":["Page large result sets with LIMIT instead of one giant read.","Never run a second command on a conn mid-large-read.","Reserve db.Conn(ctx) for sequential multi-statement flows."],"tags":["protocol","concurrency","rows","large-payload"],"backgroundTag":null,"analyzedSha":"03d76c7e07908e255ce62d126d07ede3f2365d86","analyzedAt":"2026-08-07T10:39:17.340Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}