{"record":{"id":"d095e81f88056efe","repo":"prometheus/node_exporter","slug":"error-obtaining-scsitape-class-info-s","errorCode":null,"errorMessage":"error obtaining SCSITape class info: %s","messagePattern":"error obtaining SCSITape class info: (.+?)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"collector/tapestats_linux.go","lineNumber":130,"sourceCode":"\t\t),\n\t\tresidualTotal: prometheus.NewDesc(\n\t\t\tprometheus.BuildFQName(namespace, tapeSubsystem, \"residual_total\"),\n\t\t\t\"The number of times during a read or write we found the residual amount to be non-zero. This should mean that a program is issuing a read larger thean the block size on tape. For write not all data made it to tape.\",\n\t\t\ttapeLabelNames, nil,\n\t\t),\n\t\tlogger: logger,\n\t\tfs:     fs,\n\t}, nil\n}\n\nfunc (c *tapestatsCollector) Update(ch chan<- prometheus.Metric) error {\n\ttapes, err := c.fs.SCSITapeClass()\n\tif err != nil {\n\t\tif os.IsNotExist(err) {\n\t\t\tc.logger.Debug(\"scsi_tape stats not found, skipping\")\n\t\t\treturn ErrNoData\n\t\t}\n\t\treturn fmt.Errorf(\"error obtaining SCSITape class info: %s\", err)\n\t}\n\n\tfor _, tape := range tapes {\n\t\tif c.ignoredDevicesPattern.MatchString(tape.Name) {\n\t\t\tc.logger.Debug(\"Ignoring device\", \"device\", tape.Name)\n\t\t\tcontinue\n\t\t}\n\t\tch <- prometheus.MustNewConstMetric(c.ioNow, prometheus.GaugeValue, float64(tape.Counters.InFlight), tape.Name)\n\t\tch <- prometheus.MustNewConstMetric(c.ioTimeSeconds, prometheus.CounterValue, float64(tape.Counters.IoNs)*0.000000001, tape.Name)\n\t\tch <- prometheus.MustNewConstMetric(c.othersCompletedTotal, prometheus.CounterValue, float64(tape.Counters.OtherCnt), tape.Name)\n\t\tch <- prometheus.MustNewConstMetric(c.readByteTotal, prometheus.CounterValue, float64(tape.Counters.ReadByteCnt), tape.Name)\n\t\tch <- prometheus.MustNewConstMetric(c.readsCompletedTotal, prometheus.CounterValue, float64(tape.Counters.ReadCnt), tape.Name)\n\t\tch <- prometheus.MustNewConstMetric(c.readTimeSeconds, prometheus.CounterValue, float64(tape.Counters.ReadNs)*0.000000001, tape.Name)\n\t\tch <- prometheus.MustNewConstMetric(c.residualTotal, prometheus.CounterValue, float64(tape.Counters.ResidCnt), tape.Name)\n\t\tch <- prometheus.MustNewConstMetric(c.writtenByteTotal, prometheus.CounterValue, float64(tape.Counters.WriteByteCnt), tape.Name)\n\t\tch <- prometheus.MustNewConstMetric(c.writesCompletedTotal, prometheus.CounterValue, float64(tape.Counters.WriteCnt), tape.Name)\n\t\tch <- prometheus.MustNewConstMetric(c.writeTimeSeconds, prometheus.CounterValue, float64(tape.Counters.WriteNs)*0.000000001, tape.Name)\n\t}","sourceCodeStart":112,"sourceCodeEnd":148,"githubUrl":"https://github.com/prometheus/node_exporter/blob/17ddd77c59ba27e1508e9f7894b1e55b44d6aed3/collector/tapestats_linux.go#L112-L148","documentation":"Update calls c.fs.SCSITapeClass() to read /sys/class/scsi_tape statistics. If the read fails with an error other than os.IsNotExist (which is gracefully handled by returning ErrNoData), the error is wrapped as this message. It means sysfs was reachable but reading the SCSI tape class directory or its per-device stat files failed.","triggerScenarios":"/sys/class/scsi_tape exists but a subdirectory or stat file cannot be read (I/O error, permission denied, race with device removal); the sysfs filesystem returned an unexpected error while enumerating tape devices.","commonSituations":"Faulty SCSI tape hardware generating I/O errors on stat reads; udev/sysfs races when a tape device is hot-unplugged mid-scrape; SELinux/AppArmor denying reads of scsi_tape attributes; broken --path.sysfs pointing to a partial copy of sysfs.","solutions":["Check dmesg for SCSI tape (st) device errors; fix underlying hardware/cable issues if I/O errors occur","Verify the exporter user can read /sys/class/scsi_tape and its device stat files","Re-check the --path.sysfs flag points at a real, complete sysfs tree","If the error is transient (device removal race), ignore occasional scrape failures or filter the device with --collector.tapestats.ignored-devices"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"if _, err := os.ReadDir(\"/sys/class/scsi_tape\"); err != nil {\n    // no tape devices or sysfs unreadable — disable tapestats\n}","typeGuard":null,"tryCatchPattern":"if err := coll.Update(ch); err != nil {\n    if errors.Is(err, ErrNoData) {\n        return // handled: no tape stats\n    }\n    log.Warn(\"tapestats scrape failed\", \"err\", err)\n}","preventionTips":["Filter known-bad devices with --collector.tapestats.ignored-devices regex","Monitor dmesg for st-driver I/O errors on hosts with tapes","Avoid pointing --path.sysfs at partial or synthetic trees","Accept occasional failures from device hotplug races; alert only on persistence"],"tags":["sysfs","scsi","tape","linux"],"backgroundTag":"file-read-failed","analyzedSha":"17ddd77c59ba27e1508e9f7894b1e55b44d6aed3","analyzedAt":"2026-09-07T17:54:06.211Z","contentChangedAt":"2026-09-07T17:54:06.211Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}