{"record":{"id":"46ca69d6ec59f390","repo":"navidrome/navidrome","slug":"getting-last-scan-time-w","errorCode":null,"errorMessage":"getting last scan time: %w","messagePattern":"getting last scan time: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"scanner/controller.go","lineNumber":153,"sourceCode":"\t\t\tif running.Load() {\n\t\t\t\telapsed = time.Since(startTime)\n\t\t\t} else {\n\t\t\t\t// If scan is not running, calculate elapsed time using the most recent scan time\n\t\t\t\tlastScanTime, err := s.getLastScanTime(ctx)\n\t\t\t\tif err == nil && !lastScanTime.IsZero() {\n\t\t\t\t\telapsed = lastScanTime.Sub(startTime)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn scanType, elapsed, lastErr\n}\n\nfunc (s *controller) Status(ctx context.Context) (*model.ScannerStatus, error) {\n\tlastScanTime, err := s.getLastScanTime(ctx)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"getting last scan time: %w\", err)\n\t}\n\n\tscanType, elapsed, lastErr := s.getScanInfo(ctx)\n\n\tif running.Load() {\n\t\tstatus := &model.ScannerStatus{\n\t\t\tScanning:    true,\n\t\t\tLastScan:    lastScanTime,\n\t\t\tCount:       s.count.Load(),\n\t\t\tFolderCount: s.folderCount.Load(),\n\t\t\tLastError:   lastErr,\n\t\t\tScanType:    scanType,\n\t\t\tElapsedTime: elapsed,\n\t\t}\n\t\treturn status, nil\n\t}\n\n\tcount, folderCount, err := s.getCounters(ctx)","sourceCodeStart":135,"sourceCodeEnd":171,"githubUrl":"https://github.com/navidrome/navidrome/blob/4ed7494a3293a9e9e647897ebfb9be327efd981b/scanner/controller.go#L135-L171","documentation":"Status wraps a failure from getLastScanTime with 'getting last scan time: %w', so any datastore error while fetching the last scan timestamp bubbles up as a ScannerStatus failure. The scanner itself is fine; the persistence layer answering 'when did we last scan?' failed.","triggerScenarios":"Calling controller.Status while the libraries table cannot be queried — DB unavailable, schema mismatch, or datastore error from getLastScanTime.","commonSituations":"Monitoring/dashboard endpoints hitting /api/scanner status during a DB outage; stale connection pools after a database failover; partially completed migrations.","solutions":["Check the wrapped inner error in logs ('getting libraries: ...') and fix the database connectivity issue","Restart Navidrome to rebuild DB connection pools after a database failover","Run migrations if the schema is out of date (e.g. after an upgrade)","If using an external Postgres/MySQL, verify the server is up and network/firewall allows the connection"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"status, err := ctrl.Status(ctx)\nif err != nil {\n\tif strings.Contains(err.Error(), \"getting last scan time\") {\n\t\t// DB unavailable; degrade gracefully instead of failing the endpoint\n\t\treturn &model.ScannerStatus{Scanning: false}, nil\n\t}\n\treturn nil, err\n}","preventionTips":["Wrap status endpoints with health checks on the database first","Configure DB client timeouts and reconnect policies","Degrade gracefully: return a partial status rather than failing the whole API call","Verify migrations run at startup before serving the API"],"tags":["go","scanner","database","api"],"backgroundTag":"database-query-failed","analyzedSha":"4ed7494a3293a9e9e647897ebfb9be327efd981b","analyzedAt":"2026-09-01T05:03:05.018Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}