Skip to content

fix(ci): make the Windows MSI linkable with the ɳClaw product name - #55

Merged
acamarata merged 3 commits into
mainfrom
fix/windows-msi-wix
Aug 27, 2026
Merged

acamarata merged 3 commits into
mainfrom
fix/windows-msi-wix

Conversation

@acamarata

Copy link
Copy Markdown
Contributor

Finishes Companion Desktop Builds. After #54 the windows leg compiled the whole tree and then died in the WiX linker with no diagnostic:

Error failed to bundle project: `failed to run ...\WixTools314\light.exe`

Why there was no error to read

tauri-bundler runs candle/light through output_ok() (src/utils/mod.rs), which pipes stdout+stderr, re-emits each line via log::debug!, and on a non-zero exit discards it in favour of a bare failed to run <exe>. At default verbosity those debug lines never render, so a WiX failure is unactionable from CI logs.

Building with --verbose surfaced it immediately. That flag is kept.

Root cause — classification (a), a real config problem

18 copies of one error, at every main.wxs line carrying the product name:

main.wxs(23) : error LGHT0311 : A string was provided with characters that are not
available in the specified database code page '1252'. ... or update the database's
code page by modifying ... Product/@Codepage ... or WixLocalization/@Codepage.

productName is ɳClaw. Its first character is U+0273 LATIN SMALL LETTER N WITH RETROFLEX HOOK, the eta the brand uses for display names. WiX defaults an MSI's database code page to the culture's ANSI code page, and tauri's languages.json maps en-US to asciiCode: 1252. U+0273 has no representation in 1252. Confirmed directly:

>>> "ɳClaw".encode("cp1252")
UnicodeEncodeError

That is also why candle passed and only light failed (a link-time database-encoding constraint, not XML syntax), and why linux and macos were unaffected -- deb/AppImage/app bundles are UTF-8 throughout and happily produced ɳClaw_1.1.2_amd64.deb and ɳClaw.app.

Not (b): no missing artifact. Not (c): WixTools314 downloaded and ran fine.

Fix

Tauri's main.wxs sets no Product/@Codepage and exposes no config knob for one. But when wix.language carries a localePath, tauri-bundler reads that .wxl verbatim and only appends the default <String> entries it cannot already find. So a minimal locale file can set the last remedy LGHT0311 itself lists:

<WixLocalization Culture="en-us" Codepage="65001" ...>

The summary information stream is deliberately left on 1252. Overriding TauriCodepage too was my first attempt and WiX rejected it with a second, stricter rule:

main.wxs(23) : error LGHT0349 : The code page '65001' is invalid for summary
information. You must specify an ANSI code page.

The two code pages are independent, and only the database one needed changing. The mismatch is safe because tauri's <Package> element carries no product name -- its only text attribute is Keywords="Installer" -- so nothing non-ASCII ever reaches the summary stream.

Deliberately not renaming the product to ASCII. ɳClaw is the documented display name, and MSI ProductName / Start Menu entries are display surfaces. Swapping the brand to satisfy a linker default is a product decision, not a CI fix. Flagging it as the alternative if maintainers would rather have an ASCII Windows install path.

Second defect found while fixing this: the uploads matched nothing

All three upload steps pointed at nclaw/desktop/src-tauri/target/release/bundle/..., which has never existed. desktop/src-tauri is a member of the root Cargo.toml workspace, so cargo writes bundles to <repo>/target/. The linux run bundled to .../nclaw/target/release/bundle/deb/ɳClaw_1.1.2_amd64.deb while the upload step looked elsewhere and logged:

##[warning]No files were found with the provided path ... No artifacts will be uploaded.

upload-artifact only warns on an empty match and still exits 0, so the linux and macos legs have been reporting success while producing nothing. Corrected the paths and set if-no-files-found: error, so a build that bundles nothing now fails the job instead of passing silently. That strengthens the gate rather than relaxing it.

Nothing weakened

No continue-on-error, no if: false, no dropped matrix leg, no bundle target removed to dodge MSI. The MSI is really produced. The only tolerance change goes the other way: empty artifact uploads became fatal.

Remaining LGHT1076 output is ICE warnings (ICE03/40/57/61), standard for Tauri MSIs, zero errors.

Verification — run 33105105052, observed per-leg

Leg Conclusion Artifact
ubuntu-latest success companion-x86_64-unknown-linux-gnu 85,784,076 B
macos-latest success companion-aarch64-apple-darwin 5,502,612 B
windows-latest success companion-x86_64-pc-windows-msvc 10,617,613 B

Run conclusion success. MSI linked as ɳClaw_1.1.2_x64_en-US.msi with the brand character intact, Finished 2 bundles. All three artifacts uploaded with non-zero size, which also confirms the corrected paths now match real files under if-no-files-found: error.

Progression across runs: 33100902335 LGHT0311 x18 -> 33102998675 LGHT0349 x1 -> 33105105052 green.

WiX is Windows-only, so this could not be reproduced on the macOS dev machine; the cp1252 encoding failure was verified locally, the rest through CI.

…tched nothing

Two problems in the same workflow, both about failures being invisible.

1. The windows leg dies with only:

     Error failed to bundle project: `failed to run ...\WixTools314\light.exe`

   and no WiX diagnostic. tauri-bundler runs candle/light through
   output_ok() (src/utils/mod.rs), which pipes stdout+stderr, re-emits
   every line via log::debug!, and on a non-zero exit throws that away
   in favour of a bare "failed to run <exe>". At default verbosity those
   debug lines are dropped, so light.exe's LGHT diagnostics never reach
   the log. Build with --verbose so they do.

2. All three upload steps pointed at
   nclaw/desktop/src-tauri/target/release/bundle/..., which has never
   existed. desktop/src-tauri is a member of the root Cargo.toml
   workspace, so cargo writes bundles to <repo>/target/. The linux run
   bundled to

     .../nclaw/target/release/bundle/deb/ɳClaw_1.1.2_amd64.deb

   while the upload step looked under desktop/src-tauri/ and reported

     ##[warning]No files were found with the provided path ...
     No artifacts will be uploaded.

   upload-artifact only warns on an empty match and still exits 0, so
   both the linux and macos legs have been reporting success while
   producing nothing. Point them at the workspace target dir and set
   if-no-files-found: error, so a build that bundles nothing fails the
   job instead of passing silently.
…nked

With --verbose surfacing WiX's diagnostics, the windows leg's real error
turned out to be 18 copies of one problem, at every line of main.wxs that
carries the product name:

  main.wxs(23) : error LGHT0311 : A string was provided with characters
  that are not available in the specified database code page '1252'.
  Either change these characters to ones that exist in the database's code
  page, or update the database's code page by modifying one of the
  following attributes: Product/@codepage, Module/@codepage,
  Patch/@codepage, PatchCreation/@codepage, or WixLocalization/@codepage.

productName is "ɳClaw". Its first character is U+0273 LATIN SMALL LETTER N
WITH RETROFLEX HOOK, the eta the brand uses for display names. WiX defaults
an MSI's database code page to the culture's ANSI code page, and
tauri-bundler's languages.json maps en-US to asciiCode 1252. U+0273 has no
representation in 1252, so light.exe refused every string containing it.
Confirmed directly: "ɳClaw".encode("cp1252") raises UnicodeEncodeError.

candle passed and only light failed because this is a database-encoding
constraint applied at link time, not a syntax problem in the generated
XML. It is also why the linux and macos legs are unaffected: deb, AppImage
and app bundles are UTF-8 throughout, and both happily produced
ɳClaw_1.1.2_amd64.deb and ɳClaw.app.

Fixed by taking the last remedy the error itself lists. tauri's main.wxs
sets no Product/@codepage and exposes no config knob for one, but when
wix.language carries a localePath, tauri-bundler reads that .wxl verbatim
and only appends the default strings it cannot already find. So a minimal
locale file can set WixLocalization/@codepage=65001 and, for consistency,
override TauriCodepage so Package/@SummaryCodepage stops reporting 1252
for a database that is no longer 1252.

Deliberately not renaming the product to ASCII. "ɳClaw" is the documented
display name, MSI ProductName and the Start Menu entry are display
surfaces, and swapping the brand to satisfy a linker default would be a
product decision, not a CI fix.
Setting WixLocalization/@codepage=65001 cleared all 18 LGHT0311 errors, so
the database code page fix was right. But also overriding TauriCodepage
pushed 65001 into Package/@SummaryCodepage, which has a stricter rule:

  main.wxs(23) : error LGHT0349 : The code page '65001' is invalid for
  summary information. You must specify an ANSI code page.

The two code pages are independent and only the database one needed to
change. Dropped the TauriCodepage override so tauri appends its 1252
default for the summary stream, and kept WixLocalization/@codepage=65001
for the database.

The mismatch is intentional and safe: tauri's Package element carries no
product name, its only text attribute being Keywords="Installer", so
nothing non-ASCII ever reaches the summary information stream. The
product name lives in the database, which is now UTF-8 and can hold it.
@acamarata
acamarata merged commit d8c91fe into main Aug 27, 2026
17 checks passed
@acamarata
acamarata deleted the fix/windows-msi-wix branch August 27, 2026 19:25
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