BeyondDimension/SteamTools · warning · ApplicationException

Battle.net Authenticator does not have a serial

Error message

Battle.net Authenticator does not have a serial

What it means

Thrown when importing a Battle.net (issuer == 'BattleNet') authenticator whose otpauth URI has no 'serial' query parameter. Battle.net authenticators require a serial alongside the secret, so a missing serial makes the entry unusable.

Source

Thrown at src/BD.WTTS.Client.Plugins.Authenticator/UI/ViewModels/AuthenticatorImportPageViewModel.cs:311

                {
                    throw new ApplicationException("Authenticator does not contain secret");
                }

                string? counter = query["counter"];
                if (uri.Host == "hotp" && string.IsNullOrEmpty(counter))
                {
                    throw new ApplicationException("HOTP authenticator should have a counter");
                }

                AuthenticatorDTO authenticatorDto = new();

                AuthenticatorValueDTO auth;
                if (string.Compare(issuer, "BattleNet", StringComparison.OrdinalIgnoreCase) == 0)
                {
                    string? serial = query["serial"];
                    if (string.IsNullOrEmpty(serial))
                    {
                        throw new ApplicationException("Battle.net Authenticator does not have a serial");
                    }

                    serial = serial.ToUpper();
                    if (Regex.IsMatch(serial, @"^[A-Z]{2}-?[\d]{4}-?[\d]{4}-?[\d]{4}$") == false)
                    {
                        throw new ApplicationException("Invalid serial for Battle.net Authenticator");
                    }

                    auth = new BattleNetAuthenticator();
                    //char[] decoded = Base32.getInstance().Decode(secret).Select(c => Convert.ToChar(c)).ToArray(); // this is hex string values
                    //string hex = new string(decoded);
                    //((BattleNetAuthenticator)auth).SecretKey = Authenticator.StringToByteArray(hex);

                    ((BattleNetAuthenticator)auth).SecretKey = Base32.GetInstance().Decode(secret);

                    ((BattleNetAuthenticator)auth).Serial = serial;

                    issuer = string.Empty;

View on GitHub (pinned to c16ffa08e0)

Solutions

  1. Re-export the Battle.net authenticator including both secret and serial.
  2. Obtain the serial from the Battle.net account/agent and append &serial=... to the URI.
  3. Reject the entry in the UI with a message naming the missing 'serial' field.
  4. If serial is truly unavailable, import the secret under a generic TOTP issuer instead.

Example fix

// before
if (string.IsNullOrEmpty(serial))
    throw new ApplicationException("Battle.net Authenticator does not have a serial");

// after: clearer, parameterised message
if (string.IsNullOrEmpty(serial))
    throw new ArgumentException(Strings.Import_BattleNetMissingSerial);
Defensive patterns

Strategy: validation

Validate before calling

if (issuer.Equals("BattleNet", StringComparison.OrdinalIgnoreCase))
{
    var serial = query["serial"];
    if (string.IsNullOrWhiteSpace(serial))
        errors.Add(($"Line {n}: Battle.net entry missing 'serial'.", line));
}

Type guard

bool BattleNetHasSerial(Uri u, string issuer) =>
    !issuer.Equals("BattleNet", StringComparison.OrdinalIgnoreCase)
    || !string.IsNullOrWhiteSpace(HttpUtility.ParseQueryString(u.Query)["serial"]);

Try / catch

try { ParseAuthenticator(line); }
catch (ApplicationException ex) when (ex.Message == "Battle.net Authenticator does not have a serial")
{
    importErrors.Add(($"Battle.net entry missing serial (line {n}).", line));
    continue;
}

Prevention

When it happens

Trigger: Parsing an otpauth entry whose issuer matches BattleNet (case-insensitive) but the query string has no 'serial' key or it is empty.

Common situations: Battle.net export that omitted the serial; URI truncated; entry reconstructed manually without the serial; conversion from a format that didn't store the serial.

Understand the failure class

Related errors


AI-assisted analysis of BeyondDimension/SteamTools@c16ffa08e0 (2026-08-13). Data as JSON: /api/errors/049a2b4d63a57567. Report an issue: GitHub.