Jackett/Jackett · error · ExceptionWithConfigData

errorMessage ?? "Login failed."

Error message

errorMessage ?? "Login failed."

What it means

Thrown by ImmortalSeed.ApplyConfiguration when login fails. The code posts credentials and checks for 'logout.php' in the response; if absent, it parses the page for an error cell matching '#main table td:contains("ERROR")'. If a specific error is found it is used as the message; otherwise the fallback 'Login failed.' is thrown. This is an ExceptionWithConfigData, surfaced to the user as a configuration problem.

Source

Thrown at src/Jackett.Common/Indexers/Definitions/ImmortalSeed.cs:173

        public override async Task<IndexerConfigurationStatus> ApplyConfiguration(JToken configJson)
        {
            LoadValuesFromJson(configJson);

            var pairs = new Dictionary<string, string> {
                { "username", configData.Username.Value },
                { "password", configData.Password.Value }
            };

            var response = await RequestLoginAndFollowRedirect(LoginUrl, pairs, null, true, null, LoginUrl);

            await ConfigureIfOK(response.Cookies, response.ContentString.Contains("logout.php"), () =>
            {
                var parser = new HtmlParser();
                using var document = parser.ParseDocument(response.ContentString);
                var errorMessage = document.QuerySelector("#main table td:contains(\"ERROR\")")?.TextContent.Trim();

                throw new ExceptionWithConfigData(errorMessage ?? "Login failed.", configData);
            });

            return IndexerConfigurationStatus.RequiresTesting;
        }

        protected override async Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query)
        {
            var searchParams = new Dictionary<string, string>
            {
                { "category", "0" },
                { "include_dead_torrents", "yes" },
                { "sort", GetSortBy },
                { "order", GetOrder }
            };

            var searchString = Regex.Replace(query.GetQueryString(), @"[ -._]+", " ").Trim();

            if (!string.IsNullOrWhiteSpace(searchString))

View on GitHub (pinned to adff194147)

Solutions

  1. Log in to ImmortalSeed manually with the same credentials to verify they work.
  2. If the browser login works, check for a captcha or new error element on the login page.
  3. Re-enter username and password in the Jackett indexer configuration.
  4. Confirm the account is active (not disabled/banned) on the website.
  5. Verify the ImmortalSeed site link is current.
Defensive patterns

Strategy: validation

Validate before calling

// Validate credentials before login
if (string.IsNullOrWhiteSpace(configData.Username?.Value) || string.IsNullOrWhiteSpace(configData.Password?.Value))
    throw new InvalidOperationException("ImmortalSeed username and password are required.");

Try / catch

try
{
    await indexer.ApplyConfiguration(configJson);
}
catch (ExceptionWithConfigData ex)
{
    // ex.Message is the site error or 'Login failed.'
    logger.Error("ImmortalSeed login failed: {Message}", ex.Message);
    // Prompt user to verify credentials
}

Prevention

When it happens

Trigger: POST to LoginUrl returns a page without 'logout.php' — wrong username/password, account disabled, IP ban, or a captcha/error block on the login page that the td:contains('ERROR') selector may or may not catch.

Common situations: Password changed; account disabled for inactivity/ratio; ImmortalSeed added a captcha or changed its error CSS class so the selector misses the message; wrong tracker credentials entered.

Related errors


AI-assisted analysis of Jackett/Jackett@adff194147 (2026-08-13). Data as JSON: /api/errors/1330fc04268c37ef. Report an issue: GitHub.