{"record":{"id":"7ac132d30c0cfc91","repo":"navidrome/navidrome","slug":"creating-taskqueue-schema-w","errorCode":null,"errorMessage":"creating taskqueue schema: %w","messagePattern":"creating taskqueue schema: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugins/host_taskqueue.go","lineNumber":103,"sourceCode":"// The given ctx bounds the service's background work (queue workers, cleanup loop).\nfunc newTaskQueueService(ctx context.Context, pluginName string, manager *Manager, maxConcurrency int32) (*taskQueueServiceImpl, error) {\n\tdataDir := filepath.Join(conf.Server.DataFolder.String(), \"plugins\", pluginName)\n\tif err := os.MkdirAll(dataDir, 0700); err != nil {\n\t\treturn nil, fmt.Errorf(\"creating plugin data directory: %w\", err)\n\t}\n\n\tdbPath := filepath.Join(dataDir, \"taskqueue.db\")\n\tdb, err := sql.Open(\"sqlite3\", dbPath+\"?_busy_timeout=5000&_journal_mode=WAL&_foreign_keys=off\")\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"opening taskqueue database: %w\", err)\n\t}\n\n\tdb.SetMaxOpenConns(3)\n\tdb.SetMaxIdleConns(1)\n\n\tif err := createTaskQueueSchema(db); err != nil {\n\t\tdb.Close()\n\t\treturn nil, fmt.Errorf(\"creating taskqueue schema: %w\", err)\n\t}\n\n\tctx, cancel := context.WithCancel(ctx) //nolint:gosec // cancel is stored in struct and called in Close()\n\n\ts := &taskQueueServiceImpl{\n\t\tpluginName:     pluginName,\n\t\tmanager:        manager,\n\t\tmaxConcurrency: maxConcurrency,\n\t\tdb:             db,\n\t\tctx:            ctx,\n\t\tcancel:         cancel,\n\t\tqueues:         make(map[string]*queueState),\n\t}\n\ts.invokeCallbackFn = s.defaultInvokeCallback\n\n\ts.wg.Go(s.cleanupLoop)\n\n\tlog.Debug(\"Initialized plugin taskqueue\", \"plugin\", pluginName, \"path\", dbPath, \"maxConcurrency\", maxConcurrency)","sourceCodeStart":85,"sourceCodeEnd":121,"githubUrl":"https://github.com/navidrome/navidrome/blob/4ed7494a3293a9e9e647897ebfb9be327efd981b/plugins/host_taskqueue.go#L85-L121","documentation":"This error wraps a failure from createTaskQueueSchema, which runs the CREATE TABLE statements for the task queue's queues/tasks tables on the plugin's SQLite database. If the schema cannot be created the database is closed and the service fails to start. Common causes are a corrupt or partially-written database file and SQLite I/O errors on disk.","triggerScenarios":"createTaskQueueSchema returns an error when executing DDL against taskqueue.db — e.g. the SQLite file is corrupted, locked by another process, or the disk write fails.","commonSituations":"A previous crash left a corrupt taskqueue.db (WAL files out of sync); the data directory is on a full or failing disk; an external process holds a conflicting lock on the database file; SQLite version incompatibilities with an old database file.","solutions":["Read the wrapped error from createTaskQueueSchema to identify the SQLite error code (e.g. SQLITE_CORRUPT, SQLITE_BUSY, SQLITE_FULL)","If the database is corrupt and its contents are disposable, stop the server and delete <dataFolder>/plugins/<pluginName>/taskqueue.db (plus -wal and -shm files) so it is recreated","Free disk space or fix storage issues if the error indicates SQLITE_FULL or I/O errors","Ensure no other process (backup tool, second server instance) has the database locked"],"exampleFix":"// before: corrupt db blocks startup\nrm /var/lib/app/plugins/myplugin/taskqueue.db*\n// after: server restarts and createTaskQueueSchema recreates a fresh schema","handlingStrategy":"fallback","validationCode":"// check db file health before opening service\ndbPath := filepath.Join(conf.Server.DataFolder.String(), \"plugins\", pluginName, \"taskqueue.db\")\nprobe, err := sql.Open(\"sqlite3\", dbPath+\"?_busy_timeout=5000\")\nif err == nil {\n    if _, err := probe.Exec(\"PRAGMA integrity_check;\"); err != nil {\n        os.Remove(dbPath) // recreate corrupt disposable db\n    }\n    probe.Close()\n}","typeGuard":"func isSqliteCorruptErr(err error) bool {\n    return err != nil && strings.Contains(strings.ToLower(err.Error()), \"corrupt\")\n}","tryCatchPattern":"s, err := newTaskQueueService(ctx, pluginName, mgr, maxConcurrency)\nif err != nil && strings.Contains(err.Error(), \"creating taskqueue schema\") {\n    if isSqliteCorruptErr(err) {\n        os.Remove(filepath.Join(conf.Server.DataFolder.String(), \"plugins\", pluginName, \"taskqueue.db\"))\n        s, err = newTaskQueueService(ctx, pluginName, mgr, maxConcurrency)\n    }\n}\nreturn s, err","preventionTips":["Delete -wal/-shm files together with taskqueue.db when removing a corrupt database","Monitor free disk space on the data volume","Prevent multiple server instances from sharing the same plugin data directory","Run PRAGMA integrity_check during maintenance windows"],"tags":["sqlite","database","schema","plugin-host"],"backgroundTag":"sqlite-disk-io-error","analyzedSha":"4ed7494a3293a9e9e647897ebfb9be327efd981b","analyzedAt":"2026-09-01T05:03:05.018Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}