Konloch/bytecode-viewer · error · IllegalArgumentException

factory already registered with key: ${key}

Error message

factory already registered with key: ${key}

What it means

Thrown by AbstractLoaderFactory.register when a factory has already been registered under the same key in FACTORY_CACHE. The registry enforces one factory per key so lookups are unambiguous; duplicate registration is treated as a programming/config error rather than an overwrite.

Source

Thrown at src/main/java/the/bytecode/club/bytecodeviewer/bootloader/loader/AbstractLoaderFactory.java:50

    private static final String DEFAULT_KEY = "default-factory";
    private static final Map<String, LoaderFactory<?>> FACTORY_CACHE = new HashMap<>();

    public static void register(LoaderFactory<?> factory)
    {
        register(DEFAULT_KEY, factory);
    }

    public static void register(String key, LoaderFactory<?> factory)
    {
        if (key == null || factory == null)
        {
            throw new IllegalArgumentException("null key or factory");
        }

        if (FACTORY_CACHE.containsKey(key))
        {
            throw new IllegalArgumentException("factory already registered with key: " + key);
        }

        FACTORY_CACHE.put(key, factory);
    }

    public static void unregister(String key)
    {
        if (key == null)
        {
            throw new IllegalArgumentException("null key");
        }

        if (!FACTORY_CACHE.containsKey(key))
        {
            throw new IllegalArgumentException("factory doesn't key for key: " + key);
        }

        FACTORY_CACHE.remove(key);

View on GitHub (pinned to 31430e0033)

Solutions

  1. Guard with FACTORY_CACHE check or a boolean initialized flag so registration runs once.
  2. Call AbstractLoaderFactory.unregister(key) before re-registering the same key.
  3. Use distinct, namespaced keys (e.g. plugin-id:loader-name) for each provider.
  4. In tests, unregister in teardown to reset the static registry.

Example fix

// before
register("class", new ClassLoaderFactory()); // second init throws
// after
if (findOrNull("class") == null) register("class", new ClassLoaderFactory());
Defensive patterns

Strategy: validation

Validate before calling

boolean alreadyRegistered;
try { AbstractLoaderFactory.find(key); alreadyRegistered = true; } catch (IllegalArgumentException e) { alreadyRegistered = false; }
if (!alreadyRegistered) AbstractLoaderFactory.register(key, factory);

Try / catch

try { AbstractLoaderFactory.register(key, factory); }
catch (IllegalArgumentException e) {
    if (e.getMessage() != null && e.getMessage().startsWith("factory already registered")) {
        log.debug("loader {} already registered, skipping", key); // treat as idempotent
    } else throw e;
}

Prevention

When it happens

Trigger: Calling register("myloader", factory) twice with the same key, e.g. re-running an init routine, two plugin modules registering the same loader name, or a hot-reload path that re-invokes registration without unregistering first.

Common situations: Plugin systems where multiple jars contribute the same loader key; application restart within the same JVM (static cache persists); unit tests registering fixtures without cleanup in @Before/@After.

Related errors


AI-assisted analysis of Konloch/bytecode-viewer@31430e0033 (2026-09-05). Data as JSON: /api/errors/e5a658d525192ce8. Report an issue: GitHub.