Skip to content

Est. 2011ยทMicrosoft Partner 7033487ยทDelivery under 3 minยทSupport 7 days a week

Your vault is empty.

Free Fix 1639

MSI 1639 and 1624: Invalid Command Line or Transform in Silent Deployments

11 min read Updated October 4, 2026 Installers, Runtimes & App Deployment

Fix it now

1639 is ERROR_INVALID_COMMAND_LINE – msiexec could not parse what it was given – and 1624 is ERROR_INSTALL_TRANSFORM_FAILURE, an error applying transforms, with Microsoft asking you to verify the transform paths are valid. Both are deployment faults rather than package faults: the same MSI that fails from a script installs perfectly when you double-click it.

The canonical form: switches, quoted package, property assignments with only the value quoted

msiexec /i "C:\pkg\app.msi" /qn /norestart TRANSFORMS="C:\pkg\site.mst;C:\pkg\lang.mst" INSTALLDIR="C:\Program Files\App" ALLUSERS=1 /l*v "C:\pkg\install.log"
  1. Print the exact command your script builds immediately before it runs, and read it. Most 1639 faults are visible the moment you see the expanded string.
  2. Quote the value, not the assignment. INSTALLDIR="C:\Program Files\App" parses; "INSTALLDIR=C:\Program Files\App" does not.
  3. Write public property names in capitals. Microsoft’s rule is that public property names cannot contain lowercase letters, and anything else is private and never reaches the part of the install that changes the machine.
  4. For 1624, confirm each transform exists at that exact path, is readable by the account running the install, and was generated against this package.
  5. In PowerShell, build the arguments as an array and use Start-Process msiexec -ArgumentList $args -Wait, or put --% ahead of the arguments so PowerShell stops interpreting them.

Do not mix bare file names and full paths in one TRANSFORMS list. Microsoft states plainly that you cannot use file names and paths together in the same TRANSFORMS list, and a mixed list is a common source of 1624.

If a log file appears at the path you named, the command line parsed and you are past 1639. If the transforms still fail, the next section explains what a transform validates against.

Why it happens

Windows Installer parses its own command line rather than relying on the shell, and the grammar is stricter than most command-line tools. Switches come first, then the package, then any number of property assignments in the form NAME=value. Anything the parser cannot fit into that shape produces 1639 without attempting the install – which is why the error arrives instantly and no log is written unless the logging switch itself parsed correctly.

Spaces are where this usually breaks. A path containing spaces has to be quoted, and the quotation marks must enclose only the value. Quote the whole assignment and the parser sees one long token that is not a valid property name. The same applies to the log path after /l*v, which is a separate argument and needs its own quotes. And the case rule catches people who never see an error at all: Microsoft documents that public property names cannot contain lowercase letters, and that properties set during the user interface phase and passed to the execution phase must be public – so a lowercase property parses cleanly, does nothing, and the install succeeds while ignoring you.

Transforms are passed as a property rather than a switch, and they carry more rules than most people realise. TRANSFORMS takes a semicolon-separated list applied in the order given. A leading colon means the transform is embedded in a storage inside the package rather than being a file on disk, and Microsoft notes that embedded transforms are not cached and are always obtained from the package. A leading vertical bar marks a secure-full-path transform, where the source must be at the full path passed to TRANSFORMS. And you cannot mix bare file names with full paths in the same list at all.

Quoting or spacing in the generated command

You have this one if 1639 returns immediately, no log file is created, and the command was built by concatenating strings in a script.

  1. Echo the fully expanded command to your own log before executing it, and paste that line into a Command Prompt by hand to confirm it parses.
  2. Quote each path individually: the package, each transform and the log target.
  3. Strip trailing spaces and line-continuation characters left by the script’s formatting.
  4. Rebuild the command with an argument array rather than string concatenation wherever the language supports it.

The transform path is not valid in the install context

You have this one if 1624, with the transform sitting on a network share or a mapped drive while the install runs from a deployment tool.

  1. Copy the package and every transform to a local staging folder as part of the deployment, and reference the local copies.
  2. Never use mapped drive letters; they do not exist for the account the install runs under.
  3. Where a UNC path is unavoidable, grant read access to the computer accounts as well as to users.
  4. Retry and confirm the log records each transform being applied in the order you listed.

File names and paths mixed in one TRANSFORMS list

You have this one if 1624 on a list where some entries are bare names and others are full paths, often after someone added one transform to an existing command.

  1. Pick one form for the whole list. Full paths are the safer choice for deployment.
  2. Where a transform lives inside the package, prefix it with a colon and remember that embedded transforms are never cached.
  3. Where you need the secure-full-path behaviour, prefix with a vertical bar and make sure each transform really is at the full path you pass.
  4. Retest the whole list rather than the entry you changed.

The transform was generated against a different package

You have this one if 1624 with the transform present locally and readable, on a package the vendor has since updated.

  1. Regenerate the transform against the exact package you are deploying now.
  2. Where the transform comes from a vendor, ask for the version matching your package build.
  3. If you author transforms in-house, version the base package and the transform together so they are never separated.
  4. Test the pair on a clean machine before wide deployment.

Transforms record validation rules when they are built. A transform that was valid for last quarter’s package can be rejected by this quarter’s, and that rejection is correct behaviour rather than a bug.

Policy is refusing the customisation

You have this one if 1644 rather than 1624, on machines with application control or software restriction policies applied.

  1. Read Microsoft’s wording for 1644: one or more customisations are not permitted by system policy. That is a policy decision, not a file problem.
  2. Produce a report with gpresult /h %USERPROFILE%\Desktop\gp.html and read the Windows Installer and application control sections.
  3. Check the Windows Installer machine policies under HKLM\Software\Policies\Microsoft\Windows\Installer, including TransformsSecure, which requires transforms to be cached where the user cannot write.
  4. Move the transform into a location the policy trusts, or have the policy amended, then run gpupdate /force on a test machine and retry.

Full reference

Command lines that work and command lines that do not

Written as Result
msiexec /i "C:\pkg\app.msi" /qn Correct: switch, quoted package path, quiet
msiexec /i C:\Program Files\app.msi /qn Fails: an unquoted path with a space is parsed as several arguments
INSTALLDIR="C:\Program Files\App" Correct: only the value is quoted
"INSTALLDIR=C:\Program Files\App" Fails with 1639: the whole token is not a valid assignment
TRANSFORMS="C:\pkg\a.mst;C:\pkg\b.mst" Correct: semicolon-separated full paths, applied in order
TRANSFORMS="a.mst;C:\pkg\b.mst" Fails: file names and paths cannot be mixed in one list
installdir=C:\Apps Parses, and does nothing: a lowercase name is private and never reaches the execution phase
msiexec /i "C:\pkg\app.msi" ^
  TRANSFORMS="C:\pkg\site.mst;C:\pkg\lang.mst" ^
  INSTALLDIR="C:\Program Files\App" ALLUSERS=1 ^
  /qn /norestart /l*v "C:\pkg\install.log"

Transform prefixes, and what each means

Written as Meaning
a.mst A file name; treated as secure-at-source or unsecured depending on policy
C:\pkg\a.mst A full path; treated as secure-full-path or unsecured depending on policy
:a.mst Embedded in a storage inside the package; never cached, always read from the package
|C:\pkg\a.mst Secure-full-path: the source must be at the full path passed to TRANSFORMS

The logging switch, and why it matters here

/l*v is worth adding to every unattended command line, not only when troubleshooting, because its presence or absence is itself a diagnostic. Microsoft documents that the path to the log file must already exist – the installer will not create the directory structure – so a missing log can mean either that the command line failed to parse or that the folder is not there. Create the staging folder as the first step of your deployment and that ambiguity disappears.

Internal errors you may see alongside 1624

Code Message
2226 Database: [2]. Transform failed
2247 Database: [2] Transform stream read/write failure

Both are internal messages rather than exit codes, and both point at the transform rather than at your command line. 2226 is the general statement that applying the transform failed; 2247 is more specific, a read or write failure against the transform stream itself, which is what a truncated or corrupted .mst produces. Regenerate the transform rather than editing it.

Making unattended deployment repeatable

  • Stage the package and every transform to a local folder as the first step, and reference them by absolute local path.
  • Build the argument list as an array, not by string concatenation, and log the expanded command before you run it.
  • Keep property names in capitals, and check the log to confirm the values you passed appear with the values you meant.
  • Version the transform with the package it was built against, and regenerate rather than reuse when the vendor ships a new build.
  • Treat 1639 as a script defect and 1624 as a file or policy defect. They look similar in a deployment report and they are not.

Every code this article covers

Code What it points at Source
1639 ERROR_INVALID_COMMAND_LINE: the command line passed to the installer could not be parsed Microsoft Learn
1624 ERROR_INSTALL_TRANSFORM_FAILURE: there was an error applying transforms; verify that the specified transform paths are valid Microsoft Learn
1644 ERROR_INSTALL_TRANSFORM_REJECTED: one or more customisations are not permitted by system policy Microsoft Learn
2226 Database: [2]. Transform failed – an internal message reporting that applying the transform did not succeed Microsoft Learn
2247 Database: [2] Transform stream read/write failure – a read or write against the transform stream itself failed Microsoft Learn

Confirm the fix worked

  1. A log file appears at the path you specified, which proves the command line parsed.
  2. The log records each transform being applied, in the order you listed them.
  3. The properties you passed appear in the log with the values you intended, in capitals.
  4. The same command runs through the deployment tool, not only from a Command Prompt.
  5. A second machine of the same build produces the same result from the staged copies.

Questions people ask about this

Is there anything to buy to fix this?

No. This is command-line syntax and file access. Every fix is a change to the script or to where you stage the files.

Why does the install work interactively and fail from my deployment tool?

Different account, different session, no mapped drives, no user profile. Stage the package and transforms locally and reference them by absolute local path, and the difference goes away.

How do I apply more than one transform?

List them in the TRANSFORMS property separated by semicolons, in the order you want them applied, and quote the whole list. Use full paths for all of them – Microsoft states you cannot mix file names and paths in the same list. A transform stored inside the package is referenced with a leading colon.

Why does my property have no effect even though the install succeeds?

Almost certainly because it is written in lower or mixed case. Microsoft’s rule is that public property names cannot contain lowercase letters, and only public properties are passed from the user interface phase to the execution phase. Anything else is private and ignored.

I get 1644 rather than 1624. Same fix?

No. 1644 means one or more customisations are not permitted by system policy – the transform was understood and refused. Look at the Windows Installer policies and any application control policy applied to the machine, and change the policy rather than the file.

Related error codes

Was this article helpful?

Your feedback helps us improve our documentation.

Related articles

Free Fix 0x80073D0A: Firewall Service Not Running, Low Disk Space or Network Failure Free Fix 0xC0000135 and 0xC000007B: App Will Not Start After a Runtime Install License Error MSI 1306: The File Is in Use and Setup Cannot Replace It Free Fix MSI 1402 and 1406: Could Not Open Key or Write Value During Installation
โ† Back to Knowledge Base