google/tsunami-security-scanner · critical · LinkageError

Error loading config.

Error message

Error loading config.

What it means

TsunamiCli.loadConfig() wraps any ReflectiveOperationException thrown while instantiating/using the config loader in a LinkageError with message 'Error loading config.'. The original exception (e.g. ClassNotFoundException for a custom config class) is attached as the cause.

Solutions

  1. Read the 'Caused by' of the LinkageError to see the real reflective failure.
  2. Verify the --config-loader class is fully qualified and present on the classpath.
  3. Ensure the class implements the expected loader interface (e.g. extends YamlConfigLoader) and has an accessible no-arg constructor.
  4. If no custom loader is needed, drop the flag so the default YamlConfigLoader is used.

Example fix

// before
--config-loader=com.example.MissingConfigLoader
// after
--config-loader=com.example.config.MyConfigLoader  # present on classpath, extends YamlConfigLoader
Defensive patterns

Strategy: try-catch

Validate before calling

Class.forName("com.example.MyConfigLoader"); // fails fast if not on classpath

Try / catch

try { cli.run(args); } catch (LinkageError e) { log.error("Config loading failed", e.getCause()); }

Prevention

When it happens

Trigger: Passing --config-loader pointing to a class that is not on the classpath, or a config class whose constructor reflection fails, so ClassLoader.loadClass / newInstance inside loadConfig (TsunamiCli.java:338) throws ReflectiveOperationException.

Common situations: Typo in the custom config-loader class name; custom class packaged in a jar not on the runtime classpath; class exists but lacks the expected no-arg constructor or visibility.

Related errors


AI-assisted analysis of google/tsunami-security-scanner@363ba87b35 (2026-09-13). Data as JSON: /api/errors/c42e9f76c28345d1. Report an issue: GitHub.

Appendix: source

Thrown at main/src/main/java/com/google/tsunami/main/cli/TsunamiCli.java:338

  private static TsunamiConfig loadConfig() {
    try (ScanResult scanResult = new ClassGraph().enableAllInfo().scan()) {
      ConfigLoader configLoader;
      Optional<String> loaderClass = TsunamiConfig.getSystemProperty("tsunami.config.loader");
      if (loaderClass.isPresent()
          && scanResult.getAllClassesAsMap().containsKey(loaderClass.get())) {
        configLoader =
            scanResult
                .getClassInfo(loaderClass.get())
                .loadClass(ConfigLoader.class)
                .getConstructor()
                .newInstance();
      } else {
        configLoader = new YamlConfigLoader();
      }

      return configLoader.loadConfig();
    } catch (ReflectiveOperationException e) {
      throw new LinkageError("Error loading config.", e);
    }
  }
}

View on GitHub (pinned to 363ba87b35)