Skip to content

fix(new): guard unsupported MxToolset output paths - #865

Open
GG-O-BP wants to merge 1 commit into
mendixlabs:mainfrom
GG-O-BP:fix/825-long-output-path
Open

fix(new): guard unsupported MxToolset output paths#865
GG-O-BP wants to merge 1 commit into
mendixlabs:mainfrom
GG-O-BP:fix/825-long-output-path

Conversation

@GG-O-BP

@GG-O-BP GG-O-BP commented Aug 10, 2026

Copy link
Copy Markdown

Closes #825

Summary

  • inspect the blank-project archive from the exact resolved MxToolset version before extraction
  • count the projected destination in UTF-16 code units and reject paths above MxToolset's 259-unit maximum with a shorter --output-dir recommendation
  • roll back partial output after create or post-create validation failures while preserving a pre-existing empty output directory

Why this uses the fallback

I tested the short-path staging approach proposed in the issue before implementing the guard:

Output directory Longest template destination update-widgets check MxBuild deploy
100 UTF-16 units 282 pass pass pass
180 UTF-16 units 362 pass pass PathTooLongException while exporting widgets

A subst alias also lets the tested operations use a shorter spelling, but that would require wrapping every later MxToolset invocation and make behavior depend on the alias. Staging therefore defers rather than solves the constraint for sufficiently deep projects, matching the fallback condition described in the issue comment.

Implementation

mxcli new now:

  1. resolves the exact requested MxToolset version;
  2. finds the largest embedded ZIP with a root .mpr in Mendix.Modeler.Core.dll and measures its longest entry;
  3. includes the requested <app-name>.mpr in the calculation when it is longer;
  4. rejects a projected destination above 259 UTF-16 units before creating the output; and
  5. removes output created by a failed invocation, or empties but preserves a pre-existing empty output directory.

The output identity is checked before rollback so a replaced directory is never recursively removed. Windows keeps explicit junction/subst spellings, while Unix resolves an existing symlink prefix to match the path MxToolset observes after chdir.

Verification

Automated checks:

  • go test ./... -count=1
  • go vet ./cmd/mxcli
  • GOOS=windows GOARCH=amd64 go test -c ./cmd/mxcli
  • git diff --check
  • installed-template scan against Mendix 10.24.9 and 11.12.2; both report the current 181-unit longest relative path

Focused tests cover:

  • the 259/260 boundary and the actionable error
  • UTF-16 surrogate-pair counting
  • version-specific embedded archive discovery
  • new and pre-existing empty output directories
  • rollback after partial extraction and after a missing .mpr
  • preservation of an existing output symlink
  • rejection of non-empty output before creation

Native Windows/MxToolset matrix:

  • Windows 11 Home 10.0.26200
  • Mendix/MxToolset 11.12.2
  • output directory 77 units / longest destination 259: mx create-project exit 0
  • output directory 78 units / longest destination 260: exit 1 with PathTooLongException, no .mpr, partial files before this fix
  • registry LongPathsEnabled 0 and 1 crossed with process longPathAware OFF and ON: all four 260-unit runs exited 1 with PathTooLongException
  • OFF used the shipped mx.exe; ON used the signed system dotnet.exe manifest to invoke the same mx.dll
  • LongPathsEnabled was restored to its original value (0) after the matrix

The host's Application Control blocks unsigned Go test executables, so the full Go suite ran under Rocky Linux/WSL; native Windows behavior was exercised directly with the installed MxToolset, and the package was separately compiled for windows/amd64.

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.

mxcli new fails with PathTooLongException for deep output paths and leaves partial output

1 participant