Skip to content

[TUnit.Aspire] Fail fast (and attributed) when a resource crashes during fixture startup #6342

Description

@thomhurst

[TUnit.Aspire] Fail fast (and attributed) when a resource crashes during fixture startup

Labels: enhancement, TUnit.Aspire, dx

Problem

When a resource dies during boot, AspireFixture<TAppHost> currently waits out the entire app-start timeout and then throws a generic error — e.g. "Timed out after 480s waiting for the Aspire application to start." That message:

  • costs the full timeout (here: 8 minutes of wall-clock per attempt), and
  • names nothing — it doesn't say which resource failed, its exit code, or why.

The author is left to reverse-engineer a diagnostics dump. In a real case, the true cause was chat exiting with 0xE0434352 (a .NET unhandled exception) ~40s in; the fixture nonetheless blocked until 480s and reported only the generic timeout.

Proposal

While waiting for readiness, watch resource states. If any awaited resource enters FailedToStart or Finished with a non-zero exit code, abort immediately and throw a message that names the resource, decodes the exit code, and includes its last N log lines.

Example:

Aspire startup aborted: resource 'chat' exited with code -532462766 (0xE0434352 — .NET unhandled exception)
after 41.3s (state: Finished). It was awaited by: media, web.

Last 20 log lines from 'chat':
  [chat] Unhandled exception. System.InvalidOperationException: ...
  [chat]    at ...

Exit-code decoding

Map common codes to human-readable causes:

Exit code Meaning
-532462766 / 0xE0434352 .NET unhandled managed exception
-1073741819 / 0xC0000005 Access violation (native crash)
137 SIGKILL (often OOM)
139 SIGSEGV
134 SIGABRT
0 Clean exit (a service exiting 0 during startup is usually still a misconfiguration)

Attribution

Because the fixture knows the WaitFor graph, it can report who was waiting on the crashed resource (in the repro: media.WaitFor(chat)web.WaitFor(media)), which immediately explains the cascade instead of leaving the author to chase the wrong resource (they'll otherwise blame media/web, which are only Waiting).

Acceptance criteria

  • A resource reaching FailedToStart / Finished(non-zero) during the readiness wait aborts the wait promptly (no full-timeout stall).
  • Failure message includes: resource name, decoded exit code, time-to-exit, final state, and the awaiters (WaitFor dependents).
  • Last N log lines of the crashed resource are included (pairs with the resource-log-forwarding issue).
  • A clean-exit-0 during startup is still surfaced (a web host exiting 0 mid-boot is a failure).

Rationale / impact

This single change would have converted ~40 minutes of manual archaeology (diagnostics-file parsing + a throwaway log-tap harness + exit-code lookup) into a one-line, immediately actionable failure. It's the highest-leverage DX improvement of the set.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions