go-sql-driver/mysql · error
reader '%s' is not registered
Error message
reader '%s' is not registered
What it means
Thrown by handleInFileRequest (infile.go:118) during a 'LOAD DATA LOCAL INFILE Reader::<name>' operation when no handler has been registered under <name> in the readerRegister map. The driver refuses to honor an unregistered reader name (a safety measure, mirroring the file allowlist) rather than failing later. The %s is the missing name.
Source
Thrown at infile.go:118
if idx := strings.Index(name, "Reader::"); idx == 0 || (idx > 0 && name[idx-1] == '/') { // io.Reader
// The server might return an an absolute path. See issue #355.
name = name[idx+8:]
readerRegisterLock.RLock()
handler, inMap := readerRegister[name]
readerRegisterLock.RUnlock()
if inMap {
rdr = handler()
if rdr != nil {
if cl, ok := rdr.(io.Closer); ok {
defer deferredClose(&err, cl)
}
} else {
err = fmt.Errorf("reader '%s' is <nil>", name)
}
} else {
err = fmt.Errorf("reader '%s' is not registered", name)
}
} else { // File
name = strings.Trim(name, `"`)
fileRegisterLock.RLock()
_, exists := fileRegister[name]
fileRegisterLock.RUnlock()
if mc.cfg.AllowAllFiles || exists {
var file *os.File
var fi os.FileInfo
if file, err = os.Open(name); err == nil {
defer deferredClose(&err, file)
// get file size
if fi, err = file.Stat(); err == nil {
rdr = file
if fileSize := int(fi.Size()); fileSize < packetSize {
packetSize = fileSizeView on GitHub (pinned to c426bd9379)
Solutions
- Call mysql.RegisterReaderHandler with the exact same name string used in the SQL before issuing the LOAD DATA.
- Check for typos, trailing whitespace, and case differences between the SQL 'Reader::<name>' and the registration key.
- Ensure registration runs in the same binary/process that executes the LOAD (the registry is in-memory, not shared across processes).
- If using a framework that lazy-initializes handlers, register eagerly at startup to avoid ordering bugs.
Example fix
// before: name in SQL not registered
// db.Exec("LOAD DATA LOCAL INFILE 'Reader::data' INTO TABLE t")
// after: register the exact name first
mysql.RegisterReaderHandler("data", func() io.Reader {
return strings.NewReader("a,b\n1,2\n")
})
db.Exec("LOAD DATA LOCAL INFILE 'Reader::data' INTO TABLE t") Defensive patterns
Strategy: validation
Validate before calling
// ensure a reader is registered before issuing LOAD DATA LOCAL INFILE Reader::<name>
func ensureReader(name string, h func() io.Reader) {
mysql.RegisterReaderHandler(name, h) // idempotent registration
}
func loadFromReader(db *sql.DB, name string) error {
// RegisterReaderHandler overwrites, so registering here is safe
mysql.RegisterReaderHandler(name, func() io.Reader { return strings.NewReader("") })
_, err := db.Exec(fmt.Sprintf("LOAD DATA LOCAL INFILE 'Reader::%s' INTO TABLE t", name))
return err
} Try / catch
if _, err := db.Exec("LOAD DATA LOCAL INFILE 'Reader::data' INTO TABLE t"); err != nil {
if strings.Contains(err.Error(), "is not registered") {
// register the handler then retry
}
} Prevention
- Register reader handlers eagerly at process startup, using the exact name from the SQL.
- Share a single constant for the reader name between the registration call and the SQL string.
- Remember the registry is in-process; each binary must register its own handlers.
When it happens
Trigger: Running 'LOAD DATA LOCAL INFILE Reader::mydata INTO TABLE ...' without first calling mysql.RegisterReaderHandler("mydata", ...), or with a typo in the name, or after DeregisterReaderHandler removed it.
Common situations: Forgot to register the handler in the new code path; name mismatch between the SQL string and the registration (case sensitivity, trailing spaces); handler was registered in a different process/binary; DeregisterReaderHandler ran before the LOAD; refactor that dropped the registration call.
Related errors
- reader '%s' is <nil>
- mysql: driver does not support the use of Named Parameters
- mysql: unsupported isolation level: %v
- local file '%s' is not registered
- argument count mismatch (got: %d; has: %d)
AI-assisted analysis of go-sql-driver/mysql@c426bd9379 (2026-08-04).
Data as JSON: /data/errors/d71a62099c95b45d.json.
Report an issue: GitHub.