Local -OutputPath is broken on Linux: hardcoded '\' separator makes checkpoint paths unopenable
Repo: microsoft/PAX
Version: v1.11.15
Summary
When -OutputPath is a local path, PAX normalises it to directory form by appending a hardcoded backslash:
PAX_Purview_Audit_Log_Processor_v1.11.15.ps1, lines 7240 and 7255:
if (-not $OutputPath.EndsWith('\') -and -not $OutputPath.EndsWith('/')) {
$OutputPath = $OutputPath + '\'
}
On Linux, \ is a legal filename character, not a separator. Passing -OutputPath /tmp/pax-output therefore yields /tmp/pax-output\, and every derived path is built underneath a directory that doesn't exist:
G-9: Failed to acquire checkpoint lock at /tmp/pax-output\/.pax_checkpoint_20260826_103115.json.lock:
Exception calling "Open" with "4" argument(s): "Could not find a part of the path
'/tmp/pax-output\/.pax_checkpoint_20260826_103115.json.lock'." Another process may have raced in.
The run aborts before any data is fetched.
Why the error is misleading
It is reported as a checkpoint lock contention problem — "Another process may have raced in" — which sends you looking for a stale lock or a concurrent run. The actual fault is the path separator, and the backslash is easy to miss inside a long path string.
Why it isn't caught by the shipped container guidance
fabric_resources/ documents running PAX in an Azure Container Apps Job, i.e. on Linux — but always with -OutputPath pointing at a SharePoint or OneLake URL. That takes the remote-output branch, which builds the scratch directory correctly:
line 7447-7448:
$sep = [System.IO.Path]::DirectorySeparatorChar
if (-not $OutputPath.EndsWith($sep)) { $OutputPath = $OutputPath + $sep }
So the bug only bites when a Linux host stages output locally — e.g. exporting to a local directory and then uploading, or writing to a mounted volume. Both are reasonable containerised patterns.
Reproduction
Linux container (mcr.microsoft.com/powershell:lts-7.4-ubuntu-22.04, the base used by fabric_resources/Dockerfile/PAX.Dockerfile):
pwsh -File PAX_Purview_Audit_Log_Processor_v1.11.15.ps1 \
-Rollup -IncludeUserInfo -Auth AppRegistration \
-TenantId <t> -ClientId <c> -ClientSecret <s> \
-StartDate 2026-08-23 -EndDate 2026-08-27 \
-OutputPath /tmp/pax-output \
-OutputPathUserInfo /tmp/pax-output \
-OutputPathLog /tmp/pax-output
Fails immediately with the G-9 error above.
Workaround
Pass a trailing separator on every -OutputPath*, since the append is skipped when one is already present:
-OutputPath /tmp/pax-output/
With that single change the same command runs to completion (62 partitions, rollup CSVs written).
Suggested fix
Use [System.IO.Path]::DirectorySeparatorChar at lines 7240 and 7255, matching what line 7448 already does. Optionally also accept / as a separator on Windows, which .NET handles natively.
Local
-OutputPathis broken on Linux: hardcoded'\'separator makes checkpoint paths unopenableRepo:
microsoft/PAXVersion: v1.11.15
Summary
When
-OutputPathis a local path, PAX normalises it to directory form by appending a hardcoded backslash:PAX_Purview_Audit_Log_Processor_v1.11.15.ps1, lines 7240 and 7255:On Linux,
\is a legal filename character, not a separator. Passing-OutputPath /tmp/pax-outputtherefore yields/tmp/pax-output\, and every derived path is built underneath a directory that doesn't exist:The run aborts before any data is fetched.
Why the error is misleading
It is reported as a checkpoint lock contention problem — "Another process may have raced in" — which sends you looking for a stale lock or a concurrent run. The actual fault is the path separator, and the backslash is easy to miss inside a long path string.
Why it isn't caught by the shipped container guidance
fabric_resources/documents running PAX in an Azure Container Apps Job, i.e. on Linux — but always with-OutputPathpointing at a SharePoint or OneLake URL. That takes the remote-output branch, which builds the scratch directory correctly:line 7447-7448:
So the bug only bites when a Linux host stages output locally — e.g. exporting to a local directory and then uploading, or writing to a mounted volume. Both are reasonable containerised patterns.
Reproduction
Linux container (
mcr.microsoft.com/powershell:lts-7.4-ubuntu-22.04, the base used byfabric_resources/Dockerfile/PAX.Dockerfile):Fails immediately with the
G-9error above.Workaround
Pass a trailing separator on every
-OutputPath*, since the append is skipped when one is already present:With that single change the same command runs to completion (62 partitions, rollup CSVs written).
Suggested fix
Use
[System.IO.Path]::DirectorySeparatorCharat lines 7240 and 7255, matching what line 7448 already does. Optionally also accept/as a separator on Windows, which .NET handles natively.