quarkusio/quarkus · error · CodestartStructureException

can't be used as '*' file strategy

Error message

 can't be used as '*' file strategy

What it means

The '*' filter in the codestart file-strategy spec selects the global default strategy, but only handlers implementing DefaultCodestartFileStrategyHandler are valid for it. This error means a non-default handler (e.g. one that requires special semantics) was assigned to the '*' catch-all filter, which the processor rejects.

Source

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

                            .add(new TargetFile(processedRelativeTargetPath, content.get()));
                } else {
                    final Path targetPath = targetDirectory.resolve(processedRelativeTargetPath);
                    Files.createDirectories(targetPath.getParent());
                    log.debug("ignoring file (but creating directory): %s", source.absolutePath());
                }
            } catch (IOException e) {
                throw new UncheckedIOException(e);
            }
        }
    }

    DefaultCodestartFileStrategyHandler getSelectedDefaultStrategy() {
        for (CodestartFileStrategy codestartFileStrategy : strategies) {
            if (Objects.equals(codestartFileStrategy.getFilter(), "*")) {
                if (codestartFileStrategy.getHandler() instanceof DefaultCodestartFileStrategyHandler) {
                    return (DefaultCodestartFileStrategyHandler) codestartFileStrategy.getHandler();
                }
                throw new CodestartStructureException(
                        codestartFileStrategy.getHandler().name() + " can't be used as '*' file strategy");
            }
        }
        return CodestartFileStrategyHandler.DEFAULT_STRATEGY;
    }

    Optional<CodestartFileStrategyHandler> getStrategy(final String key) {
        for (CodestartFileStrategy codestartFileStrategy : strategies) {
            if (codestartFileStrategy.test(key)) {
                return Optional.of(codestartFileStrategy.getHandler());
            }
        }
        return Optional.empty();
    }
}

View on GitHub (pinned to e1c734241f)

Solutions

  1. Change the '*' mapping to a default-capable handler (e.g. default/override/merge)
  2. Move the non-default handler to a specific file filter instead of '*'
  3. Remove the '*' entry to fall back to CodestartFileStrategyHandler.DEFAULT_STRATEGY

Example fix

# before
conflict-strategy:
  '*': merge
# after
conflict-strategy:
  '*': override
  'src/main/docker/**': merge
Defensive patterns

Strategy: validation

Validate before calling

Object h = CodestartFileStrategyHandler.BY_NAME.get(spec.get("*"));
if (!(h instanceof DefaultCodestartFileStrategyHandler))
    throw new IllegalArgumentException("'*' needs a DefaultCodestartFileStrategyHandler");

Type guard

boolean defaultCapable(String name) {
    Object h = CodestartFileStrategyHandler.BY_NAME.get(name);
    return h instanceof DefaultCodestartFileStrategyHandler;
}

Try / catch

try { buildStrategies(spec); }
catch (CodestartStructureException e) {
    if (e.getMessage().endsWith("can't be used as '*' file strategy")) { /* fix '*' mapping */ }
    else throw e;
}

Prevention

When it happens

Trigger: A codestart spec maps the '*' filter to a handler that is not a DefaultCodestartFileStrategyHandler; getSelectedDefaultStrategy (called from strategy/processLanguageDir/check methods) encounters it during generation.

Common situations: Misconfigured conflict-strategy block in codestarts.yml; copying a strategy mapping intended for a specific file filter to the '*' filter; version drift where a handler lost the default capability.

Related errors


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