Konloch/bytecode-viewer · error · IllegalArgumentException

factory doesn't key for key: ${key}

Error message

factory doesn't key for key: ${key}

What it means

Thrown by AbstractLoaderFactory.unregister when no factory is registered under the given key. Unregister is intentionally strict: removing a key that is absent means caller state and registry state have diverged. (Note the message has a typo: "factory doesn't key for key".)

Source

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

        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);
    }

    public static <T extends ExternalResource<?>> LoaderFactory<T> find()
    {
        return find(DEFAULT_KEY);
    }

    @SuppressWarnings("unchecked")
    public static <T extends ExternalResource<?>> LoaderFactory<T> find(String key)
    {
        if (key == null)
        {
            throw new IllegalArgumentException("null key");
        }

View on GitHub (pinned to 31430e0033)

Solutions

  1. Check registration existence before removing (or track keys you registered yourself).
  2. Make unregister idempotent in your code by catching/swallowing this specific case during teardown.
  3. Ensure only one cleanup path owns registry teardown.

Example fix

// before
tearDownHooks.forEach(k -> unregister(k));
// after
tearDownHooks.stream().filter(k -> isRegistered(k)).forEach(k -> unregister(k)); // or try { unregister(k); } catch (IllegalArgumentException e) { /* already gone */ }
Defensive patterns

Strategy: try-catch

Validate before calling

// only unregister keys you registered yourself in this run
if (myRegisteredKeys.remove(key)) AbstractLoaderFactory.unregister(key);

Try / catch

try { AbstractLoaderFactory.unregister(key); }
catch (IllegalArgumentException e) {
    if (e.getMessage() != null && e.getMessage().startsWith("factory doesn't")) {
        log.debug("already unregistered: {}", key); // idempotent teardown
    } else throw e;
}

Prevention

When it happens

Trigger: Calling unregister("x") when "x" was never registered, was already unregistered (double teardown), or the static cache was cleared between registration and removal, e.g. two shutdown hooks both unregistering the same key.

Common situations: Application shutdown where cleanup runs twice (context close + JVM shutdown hook); test suites sharing a static registry across test classes; renaming a loader key in config without updating the unregister call.

Related errors


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