BeyondDimension/SteamTools · warning · ApplicationException
Invalid serial for Battle.net Authenticator
Error message
Invalid serial for Battle.net Authenticator
What it means
Thrown when a Battle.net serial fails the format regex ^[A-Z]{2}-?[\d]{4}-?[\d]{4}-?[\d]{4}$ (after uppercasing). The serial must be two letters followed by three groups of four digits, with optional dashes; anything else is treated as invalid.
Source
Thrown at src/BD.WTTS.Client.Plugins.Authenticator/UI/ViewModels/AuthenticatorImportPageViewModel.cs:317
{
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;
}
else if (string.Compare(issuer, "Steam", StringComparison.OrdinalIgnoreCase) == 0)
{
auth = new SteamAuthenticator();
((SteamAuthenticator)auth).SecretKey = Base32.GetInstance().Decode(secret);
((SteamAuthenticator)auth).Serial = string.Empty;View on GitHub (pinned to c16ffa08e0)
Solutions
- Re-copy the serial exactly as shown in the Battle.net authenticator (US-XX-XXXX-XXXX-XXXX style).
- Strip spaces and ensure only letters/digits/dashes remain before validating.
- If the genuine serial uses a different format, extend the regex rather than forcing the value.
- Show the expected format in the UI error so the user can self-correct.
Example fix
// before
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");
// after: normalise dashes/spaces, then a clearer message
serial = serial.ToUpper().Replace(" ", "");
if (!Regex.IsMatch(serial, @"^[A-Z]{2}-?\d{4}-?\d{4}-?\d{4}$"))
throw new ArgumentException(string.Format(Strings.Import_BadBattleNetSerial, serial)); Defensive patterns
Strategy: validation
Validate before calling
static readonly Regex BattleNetSerial =
new(@"^[A-Z]{2}-?\d{4}-?\d{4}-?\d{4}$", RegexOptions.Compiled);
bool IsValidBattleNetSerial(string? serial)
=> !string.IsNullOrWhiteSpace(serial) && BattleNetSerial.IsMatch(serial.Trim().ToUpperInvariant());
if (issuer.Equals("BattleNet", StringComparison.OrdinalIgnoreCase) && !IsValidBattleNetSerial(query["serial"]))
errors.Add(($"Line {n}: serial format invalid (expected US-XXXX-XXXX-XXXX).", line)); Type guard
bool IsValidSerial(string? s) => !string.IsNullOrWhiteSpace(s) && Regex.IsMatch(s.Trim().ToUpperInvariant(), @"^[A-Z]{2}-?\d{4}-?\d{4}-?\d{4}$"); Try / catch
try { ParseAuthenticator(line); }
catch (ApplicationException ex) when (ex.Message == "Invalid serial for Battle.net Authenticator")
{
importErrors.Add(($"Bad Battle.net serial format (line {n}). Expected US-XXXX-XXXX-XXXX.", line));
continue;
} Prevention
- Normalize the serial (trim, uppercase, strip spaces) before validating.
- Show the expected format mask in the UI next to the serial field.
- Extend the regex if genuine serials use a different region format, rather than rejecting them.
- Report the offending value (truncated) in the error so the user can compare.
When it happens
Trigger: Importing a BattleNet entry whose serial, after ToUpper, does not match the expected two-letters + 12-digits pattern (dashes optional).
Common situations: Serial mistyped or truncated; serial copied with extra characters/spaces; serial from a different/legacy format; regional serial format that doesn't fit the pattern.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Battle.net Authenticator does not have a serial
- Import only supports otpauth://
- Import only supports otpauth://totp/ or otpauth://hotp/
- Authenticator does not contain secret
- HOTP authenticator should have a counter
AI-assisted analysis of BeyondDimension/SteamTools@c16ffa08e0 (2026-08-13).
Data as JSON: /api/errors/e60099529b6a9161.
Report an issue: GitHub.