{"record":{"id":"f2d483535f1053ec","repo":"Sonarr/Sonarr","slug":"deluge-failed-to-add-magnet-magnetlink","errorCode":null,"errorMessage":"Deluge failed to add magnet {magnetLink}","messagePattern":"Deluge failed to add magnet (.+?)","errorType":"exception","errorClass":"DownloadClientException","httpStatus":null,"severity":"error","filePath":"src/NzbDrone.Core/Download/Clients/Deluge/Deluge.cs","lineNumber":64,"sourceCode":"                {\n                    _proxy.SetTorrentLabel(downloadClientItem.DownloadId.ToLower(), Settings.TvImportedCategory, Settings);\n                }\n                catch (DownloadClientUnavailableException)\n                {\n                    _logger.Warn(\"Failed to set torrent post-import label \\\"{0}\\\" for {1} in Deluge. Does the label exist?\",\n                        Settings.TvImportedCategory,\n                        downloadClientItem.Title);\n                }\n            }\n        }\n\n        protected override string AddFromMagnetLink(RemoteEpisode remoteEpisode, string hash, string magnetLink)\n        {\n            var actualHash = _proxy.AddTorrentFromMagnet(magnetLink, Settings);\n\n            if (actualHash.IsNullOrWhiteSpace())\n            {\n                throw new DownloadClientException(\"Deluge failed to add magnet \" + magnetLink);\n            }\n\n            _proxy.SetTorrentSeedingConfiguration(actualHash, remoteEpisode.SeedConfiguration, Settings);\n\n            if (Settings.TvCategory.IsNotNullOrWhiteSpace())\n            {\n                _proxy.SetTorrentLabel(actualHash, Settings.TvCategory, Settings);\n            }\n\n            var isRecentEpisode = remoteEpisode.IsRecentEpisode();\n\n            if ((isRecentEpisode && Settings.RecentTvPriority == (int)DelugePriority.First) ||\n                (!isRecentEpisode && Settings.OlderTvPriority == (int)DelugePriority.First))\n            {\n                _proxy.MoveTorrentToTopInQueue(actualHash, Settings);\n            }\n\n            return actualHash.ToUpper();","sourceCodeStart":46,"sourceCodeEnd":82,"githubUrl":"https://github.com/Sonarr/Sonarr/blob/da2284d7eaab22ed9b2ca698af690148d691e967/src/NzbDrone.Core/Download/Clients/Deluge/Deluge.cs#L46-L82","documentation":"Thrown by Deluge.AddFromMagnetLink after _proxy.AddTorrentFromMagnet returns a null/whitespace hash. The Deluge JSON-RPC call 'core.add_torrent_magnet' succeeded at the transport layer but Deluge did not return a valid torrent hash, meaning it refused or silently rejected the magnet. This is a DownloadClientException (hard failure), so Sonarr treats the download attempt as failed rather than transiently retrying.","triggerScenarios":"AddFromMagnetLink is invoked with a magnetLink; _proxy.AddTorrentFromMagnet calls 'core.add_torrent_magnet' and the deserialized JsonRpcResponse.Result string is null, empty, or whitespace. Common when the magnet URI is malformed, the info_hash is already present and Deluge returns null, or a Deluge plugin/daemon version returns an empty result on success.","commonSituations":"Duplicate magnet already in Deluge (some Deluge versions return empty instead of the existing hash); magnet string truncated or missing the btih:xt parameter; Deluge daemon restart mid-grab; mismatched Deluge daemon version that does not support the options payload sent by AddTorrentFromMagnet.","solutions":["In Deluge Web UI, verify the magnet actually added; if a duplicate exists, remove the existing torrent and let Sonarr re-grab.","Check the magnet URI is well-formed (starts with 'magnet:?', contains 'xt=urn:btih:<40-char-hex>').","Inspect Sonarr logs for the preceding DelugeProxy trace to see the raw JSON-RPC response and confirm whether Deluge returned an error vs. an empty result.","Restart the Deluge daemon to clear a stuck state, then trigger a re-grab in Sonarr (Interactive Search -> Send)."],"exampleFix":"// before\nvar actualHash = _proxy.AddTorrentFromMagnet(magnetLink, Settings);\nif (actualHash.IsNullOrWhiteSpace())\n{\n    throw new DownloadClientException(\"Deluge failed to add magnet \" + magnetLink);\n}\n\n// after - surface the underlying Deluge error for diagnosis\nvar actualHash = _proxy.AddTorrentFromMagnet(magnetLink, Settings);\nif (actualHash.IsNullOrWhiteSpace())\n{\n    throw new DownloadClientException($\"Deluge returned no hash for magnet {magnetLink}. It may already exist; remove it from Deluge and retry.\");\n}","handlingStrategy":"validation","validationCode":"// Validate the magnet before handing it to the download client.\nprivate static readonly Regex MagnetRegex = new(@\"^magnet:\\?xt=urn:btih:[0-9a-fA-F]{40}(&.*)?$\", RegexOptions.Compiled);\n\nif (!MagnetRegex.IsMatch(magnetLink))\n{\n    _logger.Warn(\"Refusing to send malformed magnet to Deluge: {0}\", magnetLink);\n    return; // or mark the release as failed in the grab pipeline\n}","typeGuard":"private static bool IsValidMagnet(string magnet) => !string.IsNullOrWhiteSpace(magnet) && magnet.StartsWith(\"magnet:?\") && magnet.Contains(\"xt=urn:btih:\");","tryCatchPattern":"// Callers of AddFromMagnetLink (the download client base) should catch DownloadClientException\n// to mark the release failed, and DownloadClientUnavailableException to retry later.\ntry { _proxy.AddTorrentFromMagnet(magnetLink, Settings); }\ncatch (DownloadClientException ex) { _logger.Error(ex, \"Deluge add failed for magnet\"); throw; }","preventionTips":["Filter malformed magnets at the parser/indexer boundary so they never reach the download client.","Log the magnet prefix (info_hash only, not the full dn/tracker list) when this throws to diagnose duplicates.","Treat a null hash from Deluge as 'already present' first - check GetItems() before failing."],"tags":["deluge","download-client","magnet","torrent","json-rpc"],"backgroundTag":null,"analyzedSha":"da2284d7eaab22ed9b2ca698af690148d691e967","analyzedAt":"2026-08-13T15:53:02.562Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}