Skip to content

Names and Paths

Gustavo Malvestiti edited this page Aug 16, 2026 · 1 revision

The two @Config attributes have strictly separate responsibilities:

  • name — the file name, and nothing else. One component only; no slashes.
  • path — the directory (or nested directories) under the base directory. Never a file name and never a file extension.

They combine under the holder's base directory:

<baseDir> / <@Config.path()> / <@Config.name()>.<format extension>
   dirs          dirs                     file

baseDir defaults to the platform config directory (config/). path defaults to "", which places the file directly in baseDir. The extension is determined by @Config.format().json5 by default, .toml for ConfigFormat.TOML.

Declaration Directory File Resolved path
@Config(name = "mymod") config/ mymod.json5 config/mymod.json5
@Config(name = "mymod.json5") config/ mymod.json5 config/mymod.json5
@Config(name = "client", path = "mymod") config/mymod/ client.json5 config/mymod/client.json5
@Config(name = "hud", path = "mymod/gui") config/mymod/gui/ hud.json5 config/mymod/gui/hud.json5
@Config(name = "mymod", format = TOML) config/ mymod.toml config/mymod.toml

Any directory in path that does not exist is created on the first save.

Rules for name: must not be blank, must not contain / or \, and must not be exactly the format extension (e.g. .json5 alone is rejected). The format extension is appended when missing, case-insensitively, so MyMod.JSON5 is left alone.

Rules for path: relative only, /-separated, and it must stay inside baseDir after normalization. Absolute paths and .. escapes are rejected with ConfigError.INVALID_CONFIG_PATH.

Naming your files: the mod id is not automatically part of the path. Use the mod id in the file name or in the path to avoid collisions with other mods:

// Single file — name it after your mod
@Config(name = "mymod")             // → config/mymod.json5

// Several files — isolate them in your own directory
@Config(name = "client", path = "mymod")   // → config/mymod/client.json5
@Config(name = "server", path = "mymod")   // → config/mymod/server.json5

// Avoid — generic names in the shared root collide with other mods
@Config(name = "client")            // → config/client.json5 — not yours alone

Two config types that resolve to the same absolute path fail at holder construction with ConfigError.CONFLICTING_CONFIG_PATH. This is detected globally across all holders in the process.

To relocate the config root — for example, into a per-world directory or a temp directory in tests — override baseDir on the builder:

EasyConfig.holder(MyModConfig.class)
    .modId("mymod")
    .baseDir(FabricLoader.getInstance().getConfigDir().resolve("mymod"))
    .create();

Providing baseDir also means the platform config directory is never queried, which makes holders fully usable in plain unit tests without any loader present.

Clone this wiki locally