diff --git a/ConfigParser.cs b/ConfigParser.cs
index a928747729578ad1ef7a39d21e48639fe23bd0fd..aca0b1ff74114438324ad3e4a6f309065002ef9e 100644
--- a/ConfigParser.cs
+++ b/ConfigParser.cs
@@ -146,6 +146,33 @@ class ConfigNoValueException: ConfigException
 		return $"{Value.Place}: Value needed." ;
 	}
 }
+class ConfigUnusedOptionException: ConfigException
+{
+	public ConfigKeyValue Value;
+	public ConfigUnusedOptionException(ConfigKeyValue value)
+	{
+		Value = value;
+	}
+	public override string ErrorString()
+	{
+		return $"{Value.Place}: No such option." ;
+	}
+}
+class ConfigUnusedSectionException: ConfigException
+{
+	public ConfigSection Section;
+	public ConfigUnusedSectionException(ConfigSection section)
+	{
+		Section = section;
+	}
+	public override string ErrorString()
+	{
+		if(Section.SectionName == null)
+			return $"Global section not allowed." ;
+		else
+			return $"{Section.SectionName}: No such section." ;
+	}
+}
 class ConfigParseValueException: ConfigException
 {
 	public ConfigValue Value;
@@ -279,6 +306,12 @@ class ConfigKeyValue: ConfigValue
 	internal string? amen;
 	internal string? tabs;
 	public string Key {get; init;}
+	public bool Used = false;
+	public ConfigKeyValue Use()
+	{
+		Used = true;
+		return this;
+	}
 	public override string FullName
 	{
 		get => Section.SectionName != null ? $"{Section.SectionName}: {Key}" : Key;
@@ -338,6 +371,12 @@ class ConfigSection: IReadOnlyList<ConfigKeyValue>
 	public int Line;
 	List<ConfigKeyValue> values = new();
 	Dictionary<string, ConfigKeyValue> valueByName = new();
+	public bool Used = false;
+	public ConfigSection Use()
+	{
+		Used = true;
+		return this;
+	}
 	internal ConfigSection(ConfigParser _Root, string? _SectionName, int _line)
 	{
 		Root = _Root;
@@ -371,7 +410,7 @@ class ConfigSection: IReadOnlyList<ConfigKeyValue>
 	{
 		if(!valueByName.TryGetValue(key, out var r))
 			return null;
-		return r;
+		return r.Use();
 	}
 	public ConfigValue OptionalDefaultIsSectionName(string key)
 	{
@@ -381,7 +420,7 @@ class ConfigSection: IReadOnlyList<ConfigKeyValue>
 	{
 		if(!valueByName.TryGetValue(key, out var r))
 			throw new ConfigNotDefinedException(this, key);
-		return r;
+		return r.Use();
 	}
 	public bool Contains(string key)
 	{
@@ -396,6 +435,14 @@ class ConfigSection: IReadOnlyList<ConfigKeyValue>
 		}
 	}
 	public ConfigSectionNameAsValue SectionNameAsValue() => new(this);
+	public void CheckUnused()
+	{
+		foreach(ConfigKeyValue it in this)
+		{
+			if(it.Used == false)
+				throw new ConfigUnusedOptionException(it);
+		}
+	}
 }
 class ConfigParser: IReadOnlyList<ConfigSection>
 {
@@ -516,13 +563,21 @@ class ConfigParser: IReadOnlyList<ConfigSection>
 		if(key == null) return MainSection;
 		if(!sectionByName.TryGetValue(key, out var r))
 			return null;
-		return r;
+		return r.Use();
 	}
 	public ConfigSection Mandatory(string? key)
 	{
 		if(key == null) return MainSection;
 		if(!sectionByName.TryGetValue(key, out var r))
 			throw new ConfigSectionNotDefinedException(key);
-		return r;
+		return r.Use();
+	}
+	public void CheckUnused()
+	{
+		foreach(ConfigSection it in this)
+		{
+			if(it.Used == false)
+				throw new ConfigUnusedSectionException(it);
+		}
 	}
 }
diff --git a/Program.cs b/Program.cs
index edc16a96ff7fd83b63bf9c74c363f4c05dc605e8..692bb57de85d63cc1a0769c8bb731c723653daaf 100644
--- a/Program.cs
+++ b/Program.cs
@@ -251,7 +251,10 @@ refresh
 				throw new Exception($"Missing constructor of {type} module");
 			Module module = (Module) constructor.Invoke(new object[]{});
 			modules.Add(addStandardModuleWrappers(s, module, this));
+			s.Use();
+			s.CheckUnused();
 		}
+		p.CheckUnused();
 	}
 	public List<Block> Get()
 	{