BeyondDimension/SteamTools · error · HandleHostsFileException
5
5
Error message
Mark appears multiple [{0}], try resetting the Hosts file or editing the Hosts file and removing the excess Mark and try again What it means
Thrown by the hosts-file parser when a managed-section delimiter ('mark') is encountered more than once. The application wraps the host entries it owns between start/end mark tokens; 'markLength' is a HashSet tracking marks already seen, and HashSet.Add returning false signals a duplicate. A repeated mark makes the block structure ambiguous, so parsing aborts rather than risking a corrupt rewrite.
Source
Thrown at src/BD.WTTS.Client/Services.Implementation/Net/HostsFileServiceImpl.cs:444
{
backup_datas.TryAdd(bak_line_split_array[1], (bak_line_num, string.Join(' ', bak_line_split_array.ToArray())));
}
}
return null;
}
var mark = GetMarkValue(line_split_array);
if (mark == null) return true;
if (mark == MarkEnd && !markLength.Contains(MarkStart)) return null;
if (mark == BackupMarkEnd && !markLength.Contains(BackupMarkStart)) return null;
if ((mark == MarkStart || mark == BackupMarkStart) && last_line_value != null && string.IsNullOrWhiteSpace(last_line_value))
{
var removeLen = last_line_value.Length + Environment.NewLine.Length;
stringBuilder.Remove(stringBuilder.Length - removeLen, removeLen);
}
if (!markLength.Add(mark))
{
throw new HandleHostsFileException(AppResources.CommunityFix_Hosts_MarkDuplicate_.Format(mark)) { Code = HandleHostsFileException.Code_CommunityFix_Hosts_MarkDuplicate_ };
}
return null;
});
if (is_effective_value_v2 != HandleLineResult.Duplicate)
{
var is_effective_value = Convert(is_effective_value_v2);
if (!is_effective_value.HasValue) goto skip;
if (!is_effective_value.Value) goto append; // 当前行是无效值,直接写入
}
string ip, domain;
ip = line_split_array[0];
domain = line_split_array[1];
var match_domain = has_hosts && hosts!.ContainsKey(domain); // 与要修改的项匹配
if (markLength.Contains(MarkStart) && !markLength.Contains(MarkEnd)) // 在标记区域内
{
if (match_domain)
{
if (isUpdateOrRemove) // 更新值View on GitHub (pinned to c16ffa08e0)
Solutions
- Open the hosts file and delete the duplicated mark line(s) so each mark appears exactly once, then retry.
- Reset the hosts file to its default content and let the application rewrite its managed section from scratch.
- Check for a second running instance of the app or a conflicting proxy tool writing the same marks, and close it.
- Restore the hosts file from a known-good backup before retrying the operation.
Example fix
// before (hosts file has two managed blocks) # >>> WTTS BEGIN >>> 127.0.0.1 example.com # <<< WTTS END <<< # >>> WTTS BEGIN >>> <- duplicate mark 127.0.0.1 other.com # <<< WTTS END <<< // after: keep a single block, remove the duplicate # >>> WTTS BEGIN >>> 127.0.0.1 example.com 127.0.0.1 other.com # <<< WTTS END <<<
Defensive patterns
Strategy: validation
Validate before calling
// Before handing the hosts file to the parser, pre-scan for duplicate marks.
bool HasDuplicateMarks(IEnumerable<string> lines, IReadOnlySet<string> markTokens)
{
var seen = new HashSet<string>();
foreach (var raw in lines)
{
var mark = GetMarkValue(raw.Trim().Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries));
if (mark == null || !markTokens.Contains(mark)) continue;
if (!seen.Add(mark)) return true; // duplicate
}
return false;
} Try / catch
try { /* parse hosts file */ }
catch (HandleHostsFileException ex) when (ex.Code == HandleHostsFileException.Code_CommunityFix_Hosts_MarkDuplicate_)
{
// Prompt user to reset the hosts file or auto-remove the duplicate block, then retry once.
Log.Warning(TAG, $"Duplicate hosts mark: {ex.Message}");
await OfferHostsResetAsync();
} Prevention
- Always read the existing hosts file and detect existing managed marks before writing, to avoid appending a second block.
- Write managed sections atomically (temp file + replace) so a crash never leaves a half-written/duplicated mark.
- Use a single owning process; acquire a file lock or mutex before modifying the hosts file.
- On startup, validate mark uniqueness and self-heal (keep the first block) instead of throwing.
When it happens
Trigger: Invoking the hosts read/repair routine on a file where a MarkStart/MarkEnd (or BackupMarkStart/BackupMarkEnd) token occurs twice — e.g. after manual editing, a crashed prior write that left a partial block, or two tools each writing their own marks into the same hosts file.
Common situations: User hand-edited the hosts file and duplicated a managed section; a previous process crash left a half-written block; another accelerator/proxy/antivirus tool appended overlapping marks; merging two hosts files by paste.
Related errors
- Could not install certificate as it is null or empty.
- TCP port {httpProxyPort} is already occupied by other proces
- Failed to get available ports. There are no available ports.
- Could not remove certificate as it is null or empty.
AI-assisted analysis of BeyondDimension/SteamTools@c16ffa08e0 (2026-08-13).
Data as JSON: /api/errors/9653cb9bb0baa113.
Report an issue: GitHub.