microsoft / microsoft/aspire

CreateLayout on macOS produces tar archives that .NET TarReader cannot extract (PAX extended attributes)

Open
#16,782 0 comments 0 reactions 0 assignees View on GitHub
area-engineering-systems
Dominant language
C#
Stars
6.3k
Forks
991
Avg merge
2d 15h
Merged PRs (30d)
196

Description

## Problem

When building the Aspire CLI bundle on macOS via `tools/CreateLayout`, the archive creation path shells out to system `tar` (`tar -czf ...`). On macOS, `/usr/bin/tar` is `bsdtar` (libarchive). bsdtar emits PAX-format extended-attribute headers (e.g. `SCHILY.fflags`, `LIBARCHIVE.creationtime`) by default, even with `COPYFILE_DISABLE=1`.

At runtime the CLI extracts the embedded `bundle.tar.gz` with `System.Formats.Tar.TarReader`. .NET's TarReader rejects these headers with:

```
System.IO.InvalidDataException: The extended header contains invalid records.
at System.Formats.Tar.TarHeader.ReadExtendedAttributesFromBuffer
at System.Formats.Tar.TarHeader.TryGetNextExtendedAttributesEntry
at System.Formats.Tar.TarReader.GetNextEntryAsync
```

This surfaces to the user as `❌ Bundle extraction failed. Run 'aspire setup --force' to retry, or reinstall the Aspire CLI.`

## Impact

All CLI E2E tests that exercise `aspire init` (which triggers bundle extraction via `AppHostServerSession` → `BundleService.EnsureExtractedAndGetLayoutAsync`) fail on macOS hosts when the bundle is built locally via `localhive.sh`. This includes any developer iterating on JavaScript / TypeScript polyglot CLI work on Apple Silicon or Intel macs, even when targeting Linux containers via Docker Desktop.

The `aspire new` C# starter path does not trigger bundle extraction on first run, so `SmokeTests.CreateAndRunAspireStarterProject` passes; this masked the issue until JS-specific tests were added.

## Repro

```bash
./localhive.sh -o /tmp/aspire-e2e -r linux-arm64 --archive
ASPIRE_E2E_ARCHIVE=/tmp/aspire-e2e.tar.gz dotnet test tests/Aspire.Cli.EndToEnd.Tests \
-- --filter-method "*.InitTypeScriptAppHost_AugmentsExistingViteRepoAtRoot"
```

## Fix (applied)

Use the .NET `System.Formats.Tar.TarWriter` path on macOS as well as Windows in `tools/CreateLayout/Program.cs::CreateArchiveAsync`. .NET's TarWriter produces archives that round-trip cleanly through TarReader.

Branch: `davidfowl/js-monorepo-dockerfile` — commit `c210d7f6d`.

## Workarounds

- Install GNU tar (`brew install gnu-tar`) and arrange for `gtar` to be invoked instead of system `tar`.
- Build the CLI archive on Linux (or in a Linux container) instead of macOS.

Neither workaround is acceptable for routine local development on macOS.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.