apache/shenyu · error · NullPointerException

get join name is null

Error message

get join name is null

What it means

ExtensionLoader.getJoin(name) throws NullPointerException when the requested join/extension name is blank (null or whitespace). Names map to implementations registered in META-INF/shenyu/ files, so a name is mandatory to look one up.

Solutions

  1. Ensure the name passed to getJoin is a non-blank string
  2. Validate/resolve configuration before calling getJoin
  3. Use getDefaultJoin() when no specific name is needed

Example fix

// before
LoadBalance lb = loader.getJoin(config.getAlgorithm());
// after
LoadBalance lb = StringUtils.isNotBlank(config.getAlgorithm())
        ? loader.getJoin(config.getAlgorithm()) : loader.getDefaultJoin();
Defensive patterns

Strategy: validation

Validate before calling

if (StringUtils.isBlank(name)) { name = defaultName; } // resolve before lookup
LoadBalance lb = loader.getJoin(name);

Type guard

static boolean validName(String n) { return n != null && !n.trim().isEmpty(); }

Try / catch

try { return loader.getJoin(name); } catch (NullPointerException e) { log.warn("Blank extension name, using default"); return loader.getDefaultJoin(); }

Prevention

When it happens

Trigger: Calling loader.getJoin(null) or loader.getJoin("") or getJoin(" "), typically when the name comes from unvalidated configuration.

Common situations: Config property for algorithm/load-balance name never set; a null returned by an upstream lookup passed straight into getJoin; typo in variable use.

Related errors


AI-assisted analysis of apache/shenyu@567142e072 (2026-09-12). Data as JSON: /api/errors/758202c5719659f5. Report an issue: GitHub.

Appendix: source

Thrown at shenyu-spi/src/main/java/org/apache/shenyu/spi/ExtensionLoader.java:142

     * @return the default join.
     */
    public T getDefaultJoin() {
        getExtensionClassesEntity();
        if (StringUtils.isBlank(cachedDefaultName)) {
            return null;
        }
        return getJoin(cachedDefaultName);
    }
    
    /**
     * Gets join.
     *
     * @param name the name
     * @return the join.
     */
    public T getJoin(final String name) {
        if (StringUtils.isBlank(name)) {
            throw new NullPointerException("get join name is null");
        }
        ClassEntity classEntity = getExtensionClassesEntity().get(name);
        if (Objects.isNull(classEntity)) {
            throw new IllegalArgumentException(name + " name is error");
        }
        if (!classEntity.isSingleton()) {
            return (T) createExtension(classEntity);
        }
        Holder<Object> objectHolder = cachedInstances.get(name);
        if (Objects.isNull(objectHolder)) {
            cachedInstances.putIfAbsent(name, new Holder<>());
            objectHolder = cachedInstances.get(name);
        }
        Object value = objectHolder.getValue();
        if (Objects.isNull(value)) {
            synchronized (objectHolder) {
                value = objectHolder.getValue();
                if (Objects.isNull(value)) {

View on GitHub (pinned to 567142e072)