quarkusio/quarkus · error · CodestartStructureException

Found more than one file containing '{merged-content}': " +

Error message

Found more than one file containing '{merged-content}': " + f.getSourceName() + ", " + template.get().getSourceName()

What it means

ContentMergeCodestartFileStrategyHandler merges multiple codestart contributions to the same file by concatenating non-template parts and splicing them where the designated template contains the literal marker '{merged-content}'. Exactly one file may contain the marker. This error is thrown when two or more files contain it, making the merge point ambiguous.

Source

Thrown at independent-projects/tools/codestarts/src/main/java/io/quarkus/devtools/codestarts/core/strategy/ContentMergeCodestartFileStrategyHandler.java:38

    static final String NAME = "content-merge";

    @Override
    public String name() {
        return NAME;
    }

    @Override
    public void process(Path targetDirectory, String relativePath, List<TargetFile> codestartFiles, Map<String, Object> data)
            throws IOException {
        checkNotEmptyCodestartFiles(codestartFiles);
        final Path targetPath = targetDirectory.resolve(relativePath);
        Optional<TargetFile> template = Optional.empty();
        final StringBuilder mergedContent = new StringBuilder();
        for (TargetFile f : codestartFiles) {
            if (f.getContent().contains("{merged-content}")) {
                if (template.isPresent()) {
                    throw new CodestartStructureException("Found more than one file containing '{merged-content}': "
                            + f.getSourceName() + ", " + template.get().getSourceName());
                }
                template = Optional.of(f);
            } else {
                mergedContent.append(f.getContent());
            }
        }
        if (!template.isPresent() || mergedContent.length() == 0) {
            return;
        }
        createDirectories(targetPath);
        final String content = template.get().getContent();
        if (content.isBlank()) {
            return;
        }
        writeFile(targetPath, content.replace("{merged-content}", mergedContent.toString()));
    }
}

View on GitHub (pinned to e1c734241f)

Solutions

  1. Keep '{merged-content}' in exactly one contributing file for that path and remove it from the others
  2. Make the other contributions plain content fragments without the marker
  3. Rename the file in one codestart if they were never meant to merge

Example fix

// before: both A.java.qute and B.java.qute contain
class App { {merged-content} }
// after: only A.java.qute contains it; B.java.qute contains just the fragment
logger.info("started");
Defensive patterns

Strategy: validation

Validate before calling

long n = files.stream().filter(f -> f.getContent().contains("{merged-content}")).count();
if (n > 1) throw new IllegalStateException("Duplicate merge marker");

Try / catch

try { generate.generateProject(targetDir); }
catch (CodestartStructureException e) {
    if (e.getMessage().contains("{merged-content}")) { /* remove duplicate marker */ }
    else throw e;
}

Prevention

When it happens

Trigger: Two codestarts contributing to the same relative path (e.g. two extensions adding to an application class) both embed '{merged-content}' in their content, and the merge strategy processes them together.

Common situations: Composing multiple custom codestarts that each define a merge marker for the same file; copy-pasting a template containing the marker into additional contributing files.

Related errors


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