# swift-issue-reporting turns bad code paths into test failures

> IssueReporting is a Swift package that reports problems in application and library code as Xcode runtime warnings, breakpoints or assertions, and turns every report into a test failure under Swift Testing or XCTest. It suits library authors who want their own misuse to be caught in CI, and it is pointless in a codebase that never runs tests.

**pointfreeco/swift-issue-reporting** — Report issues in your application and library code as Xcode runtime warnings, breakpoints, assertions, and do so in a testable manner.

- Repository: https://github.com/pointfreeco/swift-issue-reporting
- Website: https://www.pointfree.co
- Stars: 529 · Forks: 113
- Language: Swift
- License: MIT
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/pointfreeco-swift-issue-reporting

## reportIssue flags a path that should never run

IssueReporting gives Swift code one function for saying that something went wrong in a way a developer needs to know about, without necessarily killing the process. The README's basic example puts it in a guard, on the path where an invariant is broken:

```swift
guard let lastItem = items.last
else {
  reportIssue("'items' should never be empty.")
}
```

The default behaviour is deliberately soft. When the app runs in Xcode, on simulator or device, a report shows up as an unobtrusive purple runtime warning. Execution continues, and the README describes the point of that choice as a visual way of seeing an issue has occurred without stopping the app or interrupting the workflow.

The contrast with a plain precondition is the design decision. A precondition traps, and a trap ends the session. Here the failure is recorded, and what happens with the record depends on the reporter and on the environment.

## One reporter, four very different outcomes

The reporter is configurable, and the README lists what you can turn the same call into. It can trigger a breakpoint, which is what you want when you intend to step through the problem in the debugger. It can become a precondition or a fatal error, which is what you want when the situation should truly stop execution rather than be merely visible.

Beyond those, you can write your own custom issue reporter, and the README suggests two destinations for it: OSLog, so reports land in the system log, or an external server, so reports leave the device. The package is built around that seam. Your call to reportIssue is stable, and the reporter decides what a report means.

The README also points to the Getting started page in the generated documentation, and notes that the package ships with a number of reporters and custom reporting functionality beyond the basic use. That generated documentation, hosted through Swift Package Index rather than in the repository, is where the full set of reporters and their configuration options live.

## In a test context, a report becomes a failure

This is the feature that makes the library worth adding to a package rather than writing a log line. The README states that when your code runs in a testing context, both Swift's native Testing framework and XCTest, all reported issues become test failures.

The consequences are more interesting than the first glance suggests. The README puts it as test coverage that problematic code paths are not executed. If a library has a branch that only triggers on misuse, and that branch now fails the test suite, then the failure lands in the library's own CI rather than in a user's app at runtime.

That is also what makes it possible to build testing tools for libraries that ship in the same target as the library itself. A library that wants to report a problem to whoever is using it needs the reporting mechanism and the assertion mechanism to be the same mechanism, and this is that mechanism.

## How the ecosystem uses it to catch its own misuse

The README lists the libraries that build on IssueReporting, and the pattern across them is instructive. Perception, a back-port of Swift's Observation framework, uses it to warn developers when a required special SwiftUI view is missing, and the warning includes a trace pointing at the view.

Dependencies, a general purpose dependency injection library, uses it to notify users when they access dependencies without overriding them. The effect described is runtime warnings in the simulator and test failures in tests, and the README says it forces each test to explicitly declare its dependencies, so when a new dependency is introduced to a feature, existing tests fail until they account for it.

Swift Navigation uses it to raise runtime warnings when APIs are used in unexpected ways. The Composable Architecture is described as heavily instrumented with issue reporting, and its testing tools support both Swift Testing and XCTest out of the box because of IssueReporting. Custom Dump ships test helpers powered by it, including drop-in replacements for `#expect(_ == _)` and `XCTAssertEqual` that render failures as concise diffs, plus helpers to assert against changes to data structures over time. Swift Clocks and Combine Schedulers use it to drive their test and unimplemented clocks, recording unexpected usage as issues.

## Building, formatting and running the test suite from the Makefile

The repository is a Swift package with a Makefile that gives you the four commands worth knowing. The examples target is run against an iOS simulator:

```bash
test-examples:
	xcodebuild test \
		-configuration $(CONFIG) \
		-project Examples/Examples.xcodeproj \
		-scheme Examples \
		-destination platform="iOS Simulator,name=iPhone 17"
```

The Makefile sets CONFIG to debug and derives XCODE_PATH from xcode-select. It also carries a comment explaining that the tests cannot rely on `XCTExpectFailure` because that does not exist in swift-corelibs-foundation, which is a reminder that the package is expected to work on non-Apple platforms too.

Two build targets guard the packaging rather than the behaviour. One builds with the static standard library:

```bash
build-for-static-stdlib:
	@swift build -c $(CONFIG) --static-swift-stdlib
```

The other checks that the module can be built with library evolution enabled, which is what lets the package be consumed by clients that need a stable module interface:

```bash
build-for-library-evolution:
	swift build \
		-c release \
		--target IssueReporting \
		-Xswiftc -emit-module-interface \
		-Xswiftc -enable-library-evolution
```

Formatting is handled by swift format with the ignore-unparsable-files flag, and the test-linux target runs the suite in a container.

## The Linux path runs the suite in a Docker container

The Makefile's last target is the one that makes the Linux story concrete, and it uses a container rather than a local toolchain:

```bash
test-linux:
	docker run \
		--rm \
		-v "$(PWD):$(PWD)" \
		-w "$(PWD)" \
		swift:6.0.3-focal \
		bash -c 'swift test -c $(CONFIG)'
```

The repository is mounted into the container at the same path, the working directory is set to it, and the image is the official swift:6.0.3-focal Swift image. The command that runs inside is a plain `swift test` with the same configuration variable.

That combination, a Linux container and a comment about swift-corelibs-foundation, is the clearest signal in the repository about who the package is written for. A library that only ever ran on an Apple platform could not use a fatalError-instead-of-precondition path, and could not offer a test-assertion reporter at all, because XCTest is not available there. The package does not claim official Linux support, and the documentation on the package index carries platform and Swift version badges rather than a promise. But the ability to run the tests in a Linux container is what makes cross-platform CI practical for consumers of the library.

## MIT licensed, frequent releases, and no version pinning advice

The library is released under the MIT license, with the LICENSE file at the repository root of the package, and the README is explicit about it. Nothing in the documentation suggests a restriction on commercial use, and the licence choice is a straightforward one for a dependency of this kind.

On maintenance, the repository is not archived and the last push was on 2026-10-13, the same day as release 2.1.2. Before that came 2.1.1 on 2026-09-22 and 2.1.0 on 2026-08-20, so the 2.1 line has seen several point releases in a short window.

There is a mismatch worth noting for anyone pinning. The topic tags list swift-testing and xctest, and the README says the library works with both, but the README does not document a minimum deployment target or a minimum Swift version, and it does not describe a migration path between major versions. The repository carries a Package.swift, an Examples directory with its own Xcode project and package manifest, and a Makefile, but the compatibility details live in the generated documentation on Swift Package Index rather than in the README.

## Conclusion

swift-issue-reporting is worth adopting for Swift package authors who want library misuse to fail their own test suite, and for teams migrating a codebase from silent fallbacks to explicit, testable diagnostics. It is the wrong choice for a project that does not run tests at all, since the value of the library is that a report becomes a failure rather than a warning nobody reads. Before adopting, check the reporter configuration in the package, because the default behaviour is a purple runtime warning that does not stop execution, and confirm that your own code paths that are currently tolerated in production are ones you actually want a test to fail on.

## FAQ

### What does reportIssue do in a Swift test?

When code runs in a testing context, under either Swift's native Testing framework or XCTest, all reported issues become test failures rather than warnings.

### Does reportIssue stop the app when it is called?

By default it does not. The README says it shows an unobtrusive purple runtime warning in Xcode on simulator and device, and the reporter can be configured to trigger a breakpoint, a precondition or a fatal error instead.

### Can I send IssueReporting reports somewhere other than the Xcode console?

Yes. The README says you can create your own custom issue reporter to send issues to OSLog or to an external server.

### How do I run the swift-issue-reporting tests on Linux?

The Makefile's test-linux target runs the suite in a container, using the swift:6.0.3-focal image with the repository mounted at the same path and `swift test -c $(CONFIG)` run inside.

### Which libraries already use IssueReporting?

The README names Perception, Dependencies, Swift Navigation, The Composable Architecture, Custom Dump, and Swift Clocks and Combine Schedulers, which use it to warn on library misuse and to record unexpected usage as test failures.

## Sources

- [License: MIT](https://github.com/pointfreeco/swift-issue-reporting/blob/main/LICENSE)
- [pointfreeco/swift-issue-reporting on GitHub](https://github.com/pointfreeco/swift-issue-reporting)
- [Project website](https://www.pointfree.co)
- [README](https://github.com/pointfreeco/swift-issue-reporting/blob/main/README.md)
- [Releases](https://github.com/pointfreeco/swift-issue-reporting/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/pointfreeco-swift-issue-reporting
