quarkusio/quarkus · error · CodestartStructureException

Multiple fallback found for a base codestart of type: '" + a

Error message

Multiple fallback found for a base codestart of type: '" + a.getSpec().getType() + "' that should be unique. Only one of '" + a.getSpec().getName() + "' and '" + b.getSpec().getName() + "' should be a fallback

What it means

CodestartCatalogs.getBaseSelection() throws CodestartStructureException when a duplicate-resolution for a base codestart type finds two candidates that are BOTH marked as fallback. For each base type, exactly one selected codestart plus at most one fallback is allowed; two fallbacks mean a broken catalog structure.

Source

Thrown at independent-projects/tools/codestarts/src/main/java/io/quarkus/devtools/codestarts/core/CodestartCatalogs.java:62

        return codestarts.stream().filter(c -> {
            if (!c.implementsLanguage(languageName)) {
                projectInput.log().warn(
                        c.getName() + " codestart will not be applied (doesn't implement language '" + languageName
                                + "' yet)");
                return false;
            }
            return true;
        }).collect(Collectors.toList());
    }

    static Collection<Codestart> getBaseSelection(Collection<Codestart> codestarts, Set<String> selection) {
        return codestarts.stream()
                .filter(c -> c.getSpec().getType().isBase())
                .filter(c -> c.getSpec().isFallback() || c.isSelected(selection))
                .collect(Collectors.toMap(c -> c.getSpec().getType(), c -> c, (a, b) -> {
                    // When there is multiple matches for one key, one should be selected and the other a fallback.
                    if (a.getSpec().isFallback() && b.getSpec().isFallback()) {
                        throw new CodestartStructureException(
                                "Multiple fallback found for a base codestart of type: '" + a.getSpec().getType()
                                        + "' that should be unique. Only one of '" + a.getSpec().getName() + "' and '"
                                        + b.getSpec().getName() + "' should be a fallback");
                    }
                    if (!a.getSpec().isFallback() && !b.getSpec().isFallback()) {
                        throw new CodestartException(
                                "Multiple selection for base codestart of type: '" + a.getSpec().getType()
                                        + "' that should be unique. Only one of '" + a.getSpec().getName() + "' and '"
                                        + b.getSpec().getName() + "' should be selected at once.");
                    }
                    // The selected is picked.
                    return !a.getSpec().isFallback() ? a : b;
                })).values();
    }

    static Collection<Codestart> getExtraSelection(Collection<Codestart> codestarts, Set<String> selection) {
        return codestarts.stream()
                .filter(c -> !c.getSpec().getType().isBase())

View on GitHub (pinned to e1c734241f)

Solutions

  1. Set fallback: false on one of the two codestarts of the duplicated base type.
  2. Remove the redundant custom codestart that duplicates the built-in fallback.
  3. Give the codestarts distinct types if they are meant to coexist rather than be fallback alternatives.

Example fix

# before (two codestarts)
name: custom-config
type: config
fallback: true
# after
name: custom-config
type: config
fallback: false
Defensive patterns

Strategy: validation

Validate before calling

// before registration: ensure only one fallback per base type
Map<String, Long> fallbacks = codestarts.stream()
    .filter(c -> c.getSpec().getType().isBase() && c.getSpec().isFallback())
    .collect(Collectors.groupingBy(c -> c.getSpec().getType().name(), Collectors.counting()));
if (fallbacks.values().stream().anyMatch(n -> n > 1)) throw new IllegalStateException("Duplicate fallback base codestarts");

Try / catch

try {
    var selected = CodestartCatalogs.select(catalogs, selection);
} catch (CodestartStructureException e) {
    if (e.getMessage().contains("Multiple fallback")) {
        logger.error("Duplicate fallback codestarts for one base type — fix spec files");
    }
    throw e;
}

Prevention

When it happens

Trigger: Selecting codestarts where two different codestarts of the same base type (e.g. two 'config' base codestarts) both have fallback: true, causing the Collectors.toMap merge function to detect the conflict.

Common situations: Registering a custom codestart that duplicates an existing fallback base codestart (same type) in another catalog; copy-pasting codestart definitions without clearing the fallback flag.

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/0686e07136fb959e. Report an issue: GitHub.