diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp
index 84adfb2b87..f604608c7b 100644
--- a/apps/opencs/model/doc/document.cpp
+++ b/apps/opencs/model/doc/document.cpp
@@ -204,7 +204,7 @@ void CSMDoc::Document::createBase()
     for (int i = 0; i < ESM::Skill::Length; ++i)
     {
         ESM::Skill record;
-        record.mId = ESM::Skill::indexToRefId(i);
+        record.mId = *ESM::Skill::indexToRefId(i).getIf<ESM::SkillId>();
         record.blank();
 
         getData().getSkills().add(record);
diff --git a/apps/opencs/model/world/collection.hpp b/apps/opencs/model/world/collection.hpp
index 17207ae154..9db6b3b042 100644
--- a/apps/opencs/model/world/collection.hpp
+++ b/apps/opencs/model/world/collection.hpp
@@ -15,6 +15,7 @@
 #include <QVariant>
 
 #include <components/esm3/loaddial.hpp>
+#include <components/esm3/loadskil.hpp>
 #include <components/misc/strings/lower.hpp>
 
 #include "collectionbase.hpp"
@@ -86,6 +87,13 @@ namespace CSMWorld
         return ESM::RefId::stringRefId(LandTexture::createUniqueRecordId(record.mPluginIndex, record.mIndex));
     }
 
+    inline void setRecordId(const ESM::RefId& id, ESM::Skill& record)
+    {
+        if (const auto* skillId = id.getIf<ESM::SkillId>())
+            record.mId = *skillId;
+        throw std::runtime_error("Invalid skill id: " + id.toDebugString());
+    }
+
     /// \brief Single-type record collection
     template <typename ESXRecordT>
     class Collection : public CollectionBase
diff --git a/apps/openmw/mwlua/stats.cpp b/apps/openmw/mwlua/stats.cpp
index f8dde1e68d..1eb96ebad0 100644
--- a/apps/openmw/mwlua/stats.cpp
+++ b/apps/openmw/mwlua/stats.cpp
@@ -392,6 +392,6 @@ namespace MWLua
         sol::table skills(context.mLua->sol(), sol::create);
         npcStats["skills"] = LuaUtil::makeReadOnly(skills);
         for (const ESM::Skill& skill : MWBase::Environment::get().getESMStore()->get<ESM::Skill>())
-            skills[skill.mId.serializeText()] = addIndexedAccessor<SkillStat>(skill.mId);
+            skills[ESM::RefId(skill.mId).serializeText()] = addIndexedAccessor<SkillStat>(skill.mId);
     }
 }
diff --git a/components/esm3/loadskil.cpp b/components/esm3/loadskil.cpp
index 21549df05b..06e5371ac7 100644
--- a/components/esm3/loadskil.cpp
+++ b/components/esm3/loadskil.cpp
@@ -7,33 +7,33 @@
 
 namespace ESM
 {
-    const RefId Skill::Block = RefId::stringRefId("Block");
-    const RefId Skill::Armorer = RefId::stringRefId("Armorer");
-    const RefId Skill::MediumArmor = RefId::stringRefId("MediumArmor");
-    const RefId Skill::HeavyArmor = RefId::stringRefId("HeavyArmor");
-    const RefId Skill::BluntWeapon = RefId::stringRefId("BluntWeapon");
-    const RefId Skill::LongBlade = RefId::stringRefId("LongBlade");
-    const RefId Skill::Axe = RefId::stringRefId("Axe");
-    const RefId Skill::Spear = RefId::stringRefId("Spear");
-    const RefId Skill::Athletics = RefId::stringRefId("Athletics");
-    const RefId Skill::Enchant = RefId::stringRefId("Enchant");
-    const RefId Skill::Destruction = RefId::stringRefId("Destruction");
-    const RefId Skill::Alteration = RefId::stringRefId("Alteration");
-    const RefId Skill::Illusion = RefId::stringRefId("Illusion");
-    const RefId Skill::Conjuration = RefId::stringRefId("Conjuration");
-    const RefId Skill::Mysticism = RefId::stringRefId("Mysticism");
-    const RefId Skill::Restoration = RefId::stringRefId("Restoration");
-    const RefId Skill::Alchemy = RefId::stringRefId("Alchemy");
-    const RefId Skill::Unarmored = RefId::stringRefId("Unarmored");
-    const RefId Skill::Security = RefId::stringRefId("Security");
-    const RefId Skill::Sneak = RefId::stringRefId("Sneak");
-    const RefId Skill::Acrobatics = RefId::stringRefId("Acrobatics");
-    const RefId Skill::LightArmor = RefId::stringRefId("LightArmor");
-    const RefId Skill::ShortBlade = RefId::stringRefId("ShortBlade");
-    const RefId Skill::Marksman = RefId::stringRefId("Marksman");
-    const RefId Skill::Mercantile = RefId::stringRefId("Mercantile");
-    const RefId Skill::Speechcraft = RefId::stringRefId("Speechcraft");
-    const RefId Skill::HandToHand = RefId::stringRefId("HandToHand");
+    const SkillId Skill::Block("Block");
+    const SkillId Skill::Armorer("Armorer");
+    const SkillId Skill::MediumArmor("MediumArmor");
+    const SkillId Skill::HeavyArmor("HeavyArmor");
+    const SkillId Skill::BluntWeapon("BluntWeapon");
+    const SkillId Skill::LongBlade("LongBlade");
+    const SkillId Skill::Axe("Axe");
+    const SkillId Skill::Spear("Spear");
+    const SkillId Skill::Athletics("Athletics");
+    const SkillId Skill::Enchant("Enchant");
+    const SkillId Skill::Destruction("Destruction");
+    const SkillId Skill::Alteration("Alteration");
+    const SkillId Skill::Illusion("Illusion");
+    const SkillId Skill::Conjuration("Conjuration");
+    const SkillId Skill::Mysticism("Mysticism");
+    const SkillId Skill::Restoration("Restoration");
+    const SkillId Skill::Alchemy("Alchemy");
+    const SkillId Skill::Unarmored("Unarmored");
+    const SkillId Skill::Security("Security");
+    const SkillId Skill::Sneak("Sneak");
+    const SkillId Skill::Acrobatics("Acrobatics");
+    const SkillId Skill::LightArmor("LightArmor");
+    const SkillId Skill::ShortBlade("ShortBlade");
+    const SkillId Skill::Marksman("Marksman");
+    const SkillId Skill::Mercantile("Mercantile");
+    const SkillId Skill::Speechcraft("Speechcraft");
+    const SkillId Skill::HandToHand("HandToHand");
 
     void Skill::load(ESMReader& esm, bool& isDeleted)
     {
@@ -70,9 +70,7 @@ namespace ESM
         if (!hasData)
             esm.fail("Missing SKDT");
 
-        // create an ID from the index and the name (only used in the editor and likely to change in the
-        // future)
-        mId = indexToRefId(index);
+        mId = *indexToRefId(index).getIf<SkillId>();
     }
 
     void Skill::save(ESMWriter& esm, bool /*isDeleted*/) const
diff --git a/components/esm3/loadskil.hpp b/components/esm3/loadskil.hpp
index 57680e56eb..dac7745d3f 100644
--- a/components/esm3/loadskil.hpp
+++ b/components/esm3/loadskil.hpp
@@ -14,6 +14,8 @@ namespace ESM
     class ESMReader;
     class ESMWriter;
 
+    using SkillId = StringRefId;
+
     struct MagicSchool
     {
         ESM::RefId mAreaSound;
@@ -43,7 +45,7 @@ namespace ESM
         static std::string_view getRecordType() { return "Skill"; }
 
         unsigned int mRecordFlags;
-        RefId mId;
+        SkillId mId;
 
         struct SKDTstruct
         {
@@ -61,33 +63,33 @@ namespace ESM
         float mWerewolfValue{};
         std::optional<MagicSchool> mSchool;
 
-        static const RefId Block;
-        static const RefId Armorer;
-        static const RefId MediumArmor;
-        static const RefId HeavyArmor;
-        static const RefId BluntWeapon;
-        static const RefId LongBlade;
-        static const RefId Axe;
-        static const RefId Spear;
-        static const RefId Athletics;
-        static const RefId Enchant;
-        static const RefId Destruction;
-        static const RefId Alteration;
-        static const RefId Illusion;
-        static const RefId Conjuration;
-        static const RefId Mysticism;
-        static const RefId Restoration;
-        static const RefId Alchemy;
-        static const RefId Unarmored;
-        static const RefId Security;
-        static const RefId Sneak;
-        static const RefId Acrobatics;
-        static const RefId LightArmor;
-        static const RefId ShortBlade;
-        static const RefId Marksman;
-        static const RefId Mercantile;
-        static const RefId Speechcraft;
-        static const RefId HandToHand;
+        static const SkillId Block;
+        static const SkillId Armorer;
+        static const SkillId MediumArmor;
+        static const SkillId HeavyArmor;
+        static const SkillId BluntWeapon;
+        static const SkillId LongBlade;
+        static const SkillId Axe;
+        static const SkillId Spear;
+        static const SkillId Athletics;
+        static const SkillId Enchant;
+        static const SkillId Destruction;
+        static const SkillId Alteration;
+        static const SkillId Illusion;
+        static const SkillId Conjuration;
+        static const SkillId Mysticism;
+        static const SkillId Restoration;
+        static const SkillId Alchemy;
+        static const SkillId Unarmored;
+        static const SkillId Security;
+        static const SkillId Sneak;
+        static const SkillId Acrobatics;
+        static const SkillId LightArmor;
+        static const SkillId ShortBlade;
+        static const SkillId Marksman;
+        static const SkillId Mercantile;
+        static const SkillId Speechcraft;
+        static const SkillId HandToHand;
         static constexpr int Length = 27;
 
         void load(ESMReader& esm, bool& isDeleted);