TechnitiumSoftware/DnsServer · warning · InvalidDataException
HourlyStats format is invalid.
Error message
HourlyStats format is invalid.
What it means
Thrown by the HourlyStats(BinaryReader) constructor when the first two ASCII bytes of the stream are not 'HS'. The magic header is a format guard read before the version byte: it confirms the stream is actually an hourly .stat file and not a corrupt or foreign file. Failing here means the file is not an HourlyStats file at all.
Source
Thrown at DnsServerCore/Dns/StatsManager.cs:1745
#region constructor
public HourlyStats()
{
_hourStat = new StatCounter();
_hourStat.Lock();
for (int i = 0; i < _minuteStats.Length; i++)
{
_minuteStats[i] = new StatCounter();
_minuteStats[i].Lock();
}
}
public HourlyStats(BinaryReader bR)
{
if (Encoding.ASCII.GetString(bR.BaseStream.ReadExactly(2)) != "HS") //format
throw new InvalidDataException("HourlyStats format is invalid.");
byte version = bR.ReadByte();
switch (version)
{
case 1:
_hourStat = new StatCounter();
_hourStat.Lock();
for (int i = 0; i < _minuteStats.Length; i++)
{
_minuteStats[i] = new StatCounter(bR);
_hourStat.Merge(_minuteStats[i]);
}
break;
default:
throw new InvalidDataException("HourlyStats version not supported.");View on GitHub (pinned to d0484b6c1e)
Solutions
- Delete the offending .stat file (named yyyyMMddHH.stat) so the hour is treated as empty and re-accumulated going forward.
- Verify the stats folder contains only files written by the server; remove foreign files.
- Ensure the server is stopped before backing up or copying stats files to avoid catching a half-written file.
Defensive patterns
Strategy: fallback
Validate before calling
// Skip non-HourlyStats files when scanning the stats folder.
using var fs = File.OpenRead(path);
Span<byte> magic = stackalloc byte[2];
if (fs.Read(magic) != 2 || magic[0] != (byte)'H' || magic[1] != (byte)'S')
continue; // not an HourlyStats file; ignore Try / catch
try { hourly = new HourlyStats(bR); }
catch (InvalidDataException ex) when (ex.Message == "HourlyStats format is invalid.")
{ hourly = HourlyStats.Empty; /* treat as empty hour */ } Prevention
- Stop the server before backing up the stats folder to avoid half-written files.
- Keep foreign files out of the stats directory.
- Delete zero-byte or partial .stat files found in the stats folder.
When it happens
Trigger: Opening a file in the stats folder as an HourlyStats stream when its first two bytes are not 0x48 0x53 ('HS'). Caused by a truncated/zero-byte file, a corrupt file, a non-stat file placed in the stats folder, or a partially-written file from a crash.
Common situations: Crash during stats write leaves a zero-length or partial .stat; an external process writes a file into the stats directory; disk corruption; copying unrelated files into the stats folder.
Related errors
- HourlyStats version not supported.
- StatCounter format is invalid.
- StatCounter version not supported.
- Invalid data or version not supported.
- DNS Server Cluster config file format is invalid.
AI-assisted analysis of TechnitiumSoftware/DnsServer@d0484b6c1e (2026-08-13).
Data as JSON: /api/errors/986a1e27ba1cdff1.
Report an issue: GitHub.