Skip to content

docs(generator): log file path collision warnings with detailed message - #24951

Open
Mattias-Sehlstedt wants to merge 1 commit into
OpenAPITools:masterfrom
Mattias-Sehlstedt:log-solution-to-file-path-collision
Open

Mattias-Sehlstedt wants to merge 1 commit into
OpenAPITools:masterfrom
Mattias-Sehlstedt:log-solution-to-file-path-collision

Conversation

@Mattias-Sehlstedt

@Mattias-Sehlstedt Mattias-Sehlstedt commented Sep 15, 2026

Copy link
Copy Markdown
Contributor

Add so that the generator file path collision warning also suggests a solution to the issue. Implemented as a "single warning with general details, and that following warnings references the first one. This with the aim to not increase the amount of warnings logs with more than a single log.

The background is that I have had collisions between MY_MODEL and MyModel on Windows, and the latter overriding the the first one (So I end up with a file called MYMODEL.java that contains public class MyModel). I was familiar with the solution from browsing issues in GitHub since before, but realized that it is not obvious with the warnings that exist currently.

PR checklist

  • Read the contribution guidelines.
  • Run the following to build the project and update samples:
    ./mvnw clean package || exit
    ./bin/generate-samples.sh ./bin/configs/*.yaml || exit
    ./bin/utils/export_docs_generators.sh || exit
    
    (For Windows users, please run the script in WSL)
    Commit all changed files.
    This is important, as CI jobs will verify all generator outputs of your HEAD commit as it would merge with master.
    These must match the expectations made by your contribution.
    You may regenerate an individual generator by passing the relevant config(s) as an argument to the script, for example ./bin/generate-samples.sh bin/configs/java*.
    IMPORTANT: Do NOT purge/delete any folders/files (e.g. tests) when regenerating the samples as manually written tests may be removed.
  • If your PR is targeting a particular programming language, @mention the technical committee members, so they are more likely to review the pull request.

Summary by cubic

Updates generator file path collision warnings to include a solution and avoid repeating the full message for every collision. The first collision per run now logs a detailed message pointing to modelNameMappings; later collisions log a short reference to that message. This helps users on case-insensitive filesystems who might otherwise silently overwrite files.

Written for commit 2efd3da. Summary will update on new commits.

Review in cubic

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 issues found across 1 file

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultGenerator.java">

<violation number="1" location="modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultGenerator.java:72">
P2: The primary collision warning unconditionally tells every user to fix the collision with `modelNameMappings`, but `processTemplateToFile` also writes API files, model/API docs, tests, webhooks, and supporting files, whose collisions `modelNameMappings` cannot resolve. For a non-model collision (e.g. two API or supporting files) this guidance is misleading and sends the user to a setting that will not fix their case. Make the remedy conditional on a model file collision, or keep the message generic and only name `modelNameMappings` as one example.</violation>

<violation number="2" location="modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultGenerator.java:1468">
P2: Using `once()` to emit the single primary warning does not reliably produce one warning per run. OnceLogger's cache is JVM-global and expires after 2 seconds (default), so in a generation that runs longer than 2s the primary message is re-emitted whenever a new collision appears, and in a JVM that runs several generators it is suppressed entirely after the first one while every later collision still logs 'see log FILEPATH_COLLISION' pointing at a primary that may not be present. Consider replacing `once()` with an instance-level flag so the primary is emitted exactly once per DefaultGenerator run.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

// O(1) case-insensitive duplicate check via a pre-lowercased shadow set
if (!seenFilesLower.add(absoluteTarget.toString().toLowerCase(Locale.ROOT))) {
LOGGER.warn("Duplicate file path detected. Not all operating systems can handle case sensitive file paths. path={}", absoluteTarget);
once(LOGGER).warn(FILE_PATH_COLLISION_LOG_MESSAGE);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Using once() to emit the single primary warning does not reliably produce one warning per run. OnceLogger's cache is JVM-global and expires after 2 seconds (default), so in a generation that runs longer than 2s the primary message is re-emitted whenever a new collision appears, and in a JVM that runs several generators it is suppressed entirely after the first one while every later collision still logs 'see log FILEPATH_COLLISION' pointing at a primary that may not be present. Consider replacing once() with an instance-level flag so the primary is emitted exactly once per DefaultGenerator run.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultGenerator.java, line 1468:

<comment>Using `once()` to emit the single primary warning does not reliably produce one warning per run. OnceLogger's cache is JVM-global and expires after 2 seconds (default), so in a generation that runs longer than 2s the primary message is re-emitted whenever a new collision appears, and in a JVM that runs several generators it is suppressed entirely after the first one while every later collision still logs 'see log FILEPATH_COLLISION' pointing at a primary that may not be present. Consider replacing `once()` with an instance-level flag so the primary is emitted exactly once per DefaultGenerator run.</comment>

<file context>
@@ -1461,7 +1465,9 @@ private File processTemplateToFile(Map<String, Object> templateData, String temp
                 // O(1) case-insensitive duplicate check via a pre-lowercased shadow set
                 if (!seenFilesLower.add(absoluteTarget.toString().toLowerCase(Locale.ROOT))) {
-                    LOGGER.warn("Duplicate file path detected. Not all operating systems can handle case sensitive file paths. path={}", absoluteTarget);
+                    once(LOGGER).warn(FILE_PATH_COLLISION_LOG_MESSAGE);
+                    LOGGER.warn("Duplicate file path detected. Not all operating systems can handle case sensitive file paths, see log '{}' for more information. path={}",
+                            FILE_PATH_COLLISION_LOG, absoluteTarget);
</file context>

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The once() call is currently the preferred way of forwarding information to the client in a less noisy way. Having it bound to an instance-level flag comes with its own flaws, and leaves us to reason about whether the Generator should become stateful and to what degree processTemplateToFile is to be invoked.

Having it tied to once() is better currently in my opinion, and an accidental omission of FILEPATH_COLLISION in uniquely executed workflows is still a better pointer than nothing.

private static final String FILE_PATH_COLLISION_LOG = "FILEPATH_COLLISION";
private static final String FILE_PATH_COLLISION_LOG_MESSAGE =
FILE_PATH_COLLISION_LOG + ": File path collision detected. Files may be overwritten by later-processed collisions. " +
"Use the 'modelNameMappings' customization setting to control the naming of colliding models.";

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: The primary collision warning unconditionally tells every user to fix the collision with modelNameMappings, but processTemplateToFile also writes API files, model/API docs, tests, webhooks, and supporting files, whose collisions modelNameMappings cannot resolve. For a non-model collision (e.g. two API or supporting files) this guidance is misleading and sends the user to a setting that will not fix their case. Make the remedy conditional on a model file collision, or keep the message generic and only name modelNameMappings as one example.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultGenerator.java, line 72:

<comment>The primary collision warning unconditionally tells every user to fix the collision with `modelNameMappings`, but `processTemplateToFile` also writes API files, model/API docs, tests, webhooks, and supporting files, whose collisions `modelNameMappings` cannot resolve. For a non-model collision (e.g. two API or supporting files) this guidance is misleading and sends the user to a setting that will not fix their case. Make the remedy conditional on a model file collision, or keep the message generic and only name `modelNameMappings` as one example.</comment>

<file context>
@@ -66,6 +66,10 @@
+    private static final String FILE_PATH_COLLISION_LOG = "FILEPATH_COLLISION";
+    private static final String FILE_PATH_COLLISION_LOG_MESSAGE =
+            FILE_PATH_COLLISION_LOG + ": File path collision detected. Files may be overwritten by later-processed collisions. " +
+            "Use the 'modelNameMappings' customization setting to control the naming of colliding models.";
     private static final String METADATA_DIR = ".openapi-generator";
     protected final Logger LOGGER = LoggerFactory.getLogger(DefaultGenerator.class);
</file context>

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have made the log message more agnostic to the precise scenario but that it still first and foremost suggests modelNameMappings since that is the most common scenario.

@Mattias-Sehlstedt
Mattias-Sehlstedt force-pushed the log-solution-to-file-path-collision branch from 98beb61 to 2efd3da Compare September 15, 2026 21:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant