{"id":"d71a62099c95b45d","repo":"go-sql-driver/mysql","slug":"reader-s-is-not-registered","errorCode":null,"errorMessage":"reader '%s' is not registered","messagePattern":"reader '(.+?)' is not registered","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"infile.go","lineNumber":118,"sourceCode":"\tif idx := strings.Index(name, \"Reader::\"); idx == 0 || (idx > 0 && name[idx-1] == '/') { // io.Reader\n\t\t// The server might return an an absolute path. See issue #355.\n\t\tname = name[idx+8:]\n\n\t\treaderRegisterLock.RLock()\n\t\thandler, inMap := readerRegister[name]\n\t\treaderRegisterLock.RUnlock()\n\n\t\tif inMap {\n\t\t\trdr = handler()\n\t\t\tif rdr != nil {\n\t\t\t\tif cl, ok := rdr.(io.Closer); ok {\n\t\t\t\t\tdefer deferredClose(&err, cl)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\terr = fmt.Errorf(\"reader '%s' is <nil>\", name)\n\t\t\t}\n\t\t} else {\n\t\t\terr = fmt.Errorf(\"reader '%s' is not registered\", name)\n\t\t}\n\t} else { // File\n\t\tname = strings.Trim(name, `\"`)\n\t\tfileRegisterLock.RLock()\n\t\t_, exists := fileRegister[name]\n\t\tfileRegisterLock.RUnlock()\n\t\tif mc.cfg.AllowAllFiles || exists {\n\t\t\tvar file *os.File\n\t\t\tvar fi os.FileInfo\n\n\t\t\tif file, err = os.Open(name); err == nil {\n\t\t\t\tdefer deferredClose(&err, file)\n\n\t\t\t\t// get file size\n\t\t\t\tif fi, err = file.Stat(); err == nil {\n\t\t\t\t\trdr = file\n\t\t\t\t\tif fileSize := int(fi.Size()); fileSize < packetSize {\n\t\t\t\t\t\tpacketSize = fileSize","sourceCodeStart":100,"sourceCodeEnd":136,"githubUrl":"https://github.com/go-sql-driver/mysql/blob/c426bd93799de0f0e094c8f0582872c529d0ed0a/infile.go#L100-L136","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: name in SQL not registered\n// db.Exec(\"LOAD DATA LOCAL INFILE 'Reader::data' INTO TABLE t\")\n\n// after: register the exact name first\nmysql.RegisterReaderHandler(\"data\", func() io.Reader {\n    return strings.NewReader(\"a,b\\n1,2\\n\")\n})\ndb.Exec(\"LOAD DATA LOCAL INFILE 'Reader::data' INTO TABLE t\")","handlingStrategy":"validation","validationCode":"// ensure a reader is registered before issuing LOAD DATA LOCAL INFILE Reader::<name>\nfunc ensureReader(name string, h func() io.Reader) {\n    mysql.RegisterReaderHandler(name, h) // idempotent registration\n}\nfunc loadFromReader(db *sql.DB, name string) error {\n    // RegisterReaderHandler overwrites, so registering here is safe\n    mysql.RegisterReaderHandler(name, func() io.Reader { return strings.NewReader(\"\") })\n    _, err := db.Exec(fmt.Sprintf(\"LOAD DATA LOCAL INFILE 'Reader::%s' INTO TABLE t\", name))\n    return err\n}","typeGuard":null,"tryCatchPattern":"if _, err := db.Exec(\"LOAD DATA LOCAL INFILE 'Reader::data' INTO TABLE t\"); err != nil {\n    if strings.Contains(err.Error(), \"is not registered\") {\n        // register the handler then retry\n    }\n}","preventionTips":["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."],"tags":["load-data","infile","reader-handler","api-misuse"],"analyzedSha":"c426bd93799de0f0e094c8f0582872c529d0ed0a","analyzedAt":"2026-08-04T21:52:59.219Z","schemaVersion":2}