{"record":{"id":"1a1f326634928eeb","repo":"Anuken/Mindustry","slug":"two-content-objects-defined-with-the-same-name","errorCode":null,"errorMessage":"Two content objects defined with the same name: '{content.name}'","messagePattern":"Two content objects defined with the same name: '(.+?)'","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"core/src/mindustry/core/ContentLoader.java","lineNumber":197,"sourceCode":"\n    public void setCurrentMod(@Nullable LoadedMod mod){\n        this.currentMod = mod;\n    }\n\n    public String transformName(String name){\n        return currentMod == null ? name : currentMod.name + \"-\" + name;\n    }\n\n    public void handleMappableContent(MappableContent content){\n        if(contentNameMap[content.getContentType().ordinal()].containsKey(content.name)){\n            var list = contentMap[content.getContentType().ordinal()];\n\n            //this method is only called when registering content, and after handleContent.\n            //If this is the last registered content, and it is invalid, make sure to remove it from the list to prevent invalid stuff from being registered\n            if(list.size > 0 && list.peek() == content){\n                list.pop();\n            }\n            throw new IllegalArgumentException(\"Two content objects defined with the same name: '\" + content.name + \"'\");\n        }\n        if(currentMod != null){\n            content.minfo.mod = currentMod;\n            if(content.minfo.sourceFile == null){\n                content.minfo.sourceFile = new Fi(content.name);\n            }\n        }\n        contentNameMap[content.getContentType().ordinal()].put(content.name, content);\n        nameMap.put(content.name, content);\n    }\n\n    public void setTemporaryMapper(MappableContent[][] temporaryMapper){\n        this.temporaryMapper = temporaryMapper;\n    }\n\n    /** @return the last registered content with the specified name. Note that the content loader makes no attempt to resolve name conflicts. This method can be unreliable. */\n    public @Nullable MappableContent byName(String name){\n        return nameMap.get(name);","sourceCodeStart":179,"sourceCodeEnd":215,"githubUrl":"https://github.com/Anuken/Mindustry/blob/f695ad7e60323ebced984fa26d0bcf0bc54296b4/core/src/mindustry/core/ContentLoader.java#L179-L215","documentation":"Thrown by ContentLoader.handleMappableContent when a second MappableContent is registered with a name that already exists in the same ContentType bucket. ContentLoader keys every block/item/liquid/unit-type/etc. by unique name so it can resolve them later by name; a duplicate name makes the registry ambiguous. On collision it also pops the offending (last-pushed) entry off the content list so an invalid object is not left registered. This fires during content loading, so it is almost always a startup-time crash.","triggerScenarios":"Calling content registration for two MappableContent objects that resolve to the same final name (mod prefix + name) within the same ContentType. Concretely: a mod re-declares a vanilla block name, two mods use the same content name without distinct prefixes, or the same content is registered twice (double init). The check is contentNameMap[contentType].containsKey(content.name).","commonSituations":"A mod author overrides/renames a vanilla block to its existing name; two enabled mods each define a block named 'copper-wall'; a custom ContentType registration loop runs twice due to a mod loader bug; merging content packs causes collisions. The mod prefix (currentMod.name + '-') only disambiguates when one of the two is modded.","solutions":["Inspect the full stack trace to find which mod/content calls handleMappableContent for the duplicated name (the name is in the message).","Rename the offending content in your mod so its final name is unique, OR ensure the mod prefix differs (the loader prefixes modded names with currentMod.name + '-').","If two mods collide, disable one or contact the author; load order does not fix a true name clash.","If you control both, namespace your content names by mod id (e.g. 'mymod-copper-wall') rather than reusing vanilla names."],"exampleFix":"// before (mod redefines a vanilla name)\ncontent.register(new Wall(\"copper-wall\"){{...}}); // collides with vanilla\n\n// after\ncontent.register(new Wall(\"mymod-copper-wall\"){{...}});","handlingStrategy":"validation","validationCode":"// before registering, check the loader for an existing name\nif(Vars.content.getByName(content.getContentType(), content.name) != null){\n    throw new IllegalStateException(\"Content name already in use: \" + content.name);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Namespace all modded content names with the mod id to avoid clashing with vanilla or other mods.","Never reuse vanilla content names; pick a distinct final name.","During mod development, run with only your mod enabled to isolate collisions.","Grep your content registration calls for duplicate literal names."],"tags":["content","registration","modding","startup","naming"],"backgroundTag":null,"analyzedSha":"f695ad7e60323ebced984fa26d0bcf0bc54296b4","analyzedAt":"2026-08-14T04:31:16.262Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}