This page covers the failure modes we hit while verifying snapview against external app projects such as Tateemi and Dawasah.
Use this order before reaching for lower-level commands:
snapview doctor --scheme MyApp
snapview watch --scheme MyApp
snapview gallerydoctortells you what is broken and how to fix it.watchis the default local loop and will bootstrap stale preparation state by runningpreparewhen it can.galleryprints or regenerates the current.snapview/gallery.htmlpage.
Cause:
snapviewis preview-driven. It renders discovered#Previewblocks, not arbitrary SwiftUI views.
How to confirm:
snapview listIf a screen is missing from the list, snapview cannot render it yet.
How to fix:
- Add a
#Previewblock for every screen or state you want rendered. - Prefer explicit preview names for gallery output.
- If the screen needs sample state, build that state in preview fixtures instead of relying on live dependencies.
Example:
#Preview("Dashboard") {
DashboardView(store: .preview)
}
#Preview("Dashboard - Empty State") {
DashboardView(store: .previewEmpty)
}Then rerun:
snapview prepare --scheme MyAppTypical error:
Cannot code sign because the target does not have an Info.plist file
Cause:
- The app project has a unit-test target, but that target is missing both:
GENERATE_INFOPLIST_FILE = YES- and a valid
INFOPLIST_FILE
How to fix:
- In the test target build settings, set
GENERATE_INFOPLIST_FILE = YES. - Or set
INFOPLIST_FILEto a real plist file.
What snapview init does:
- When
snapview initcreates or patches its generated test target files, it configures generatedInfo.plistsupport. - Older existing test targets may still need manual repair.
Minimum expected test-target settings:
BUNDLE_LOADER = $(TEST_HOST)
TEST_HOST = $(BUILT_PRODUCTS_DIR)/MyApp.app/MyApp
GENERATE_INFOPLIST_FILE = YES
After fixing the target, rerun:
snapview prepare --scheme MyAppTypical warning:
Warning: couldn't copy PNGs to /path/to/project/.snapview; using runtime output instead.
Cause:
snapviewrendered successfully, but the final copy step back into the external project's.snapviewfolder failed due to permissions or sandbox constraints.
How to fix or work around:
- Use the runtime output path printed by
snapview. - If you want the PNGs inside the project, make sure the project directory is writable from the environment running
snapview.
What this means:
- The render is good.
- The failure is only in the final copy-back step.
Cause:
snapview preparerefreshed the generated registry and test bundle, but the already-running host is still using the previous prepared artifacts.
What watch does:
watchuses the shared host supervisor and restarts stale hosts after a successfulprepare.- Manual host sessions you started outside
watchstill need manual restart if you are not using the watch loop.
How to fix:
snapview host stop
snapview host start --scheme MyAppRecommended workflow after preview changes:
snapview prepare --scheme MyApp
snapview host stop
snapview host start --scheme MyApp
snapview render-all --scheme MyAppCause:
- The prepared metadata no longer matches the current project, scheme, or test target.
- This usually happens after switching projects, changing the scheme, or regenerating test artifacts.
What watch does:
watchtreats stale preparation state as recoverable at startup and will run its ownprepare.- Other blocking project errors, such as missing previews or broken test-target settings, still stop startup.
How to fix:
snapview prepare --scheme MyAppIf you are using the persistent host, restart it afterward.
Expected behavior now:
watchshould attempt one refresh cycle for a settled snapshot.- If that cycle fails, it should wait for the next file change before retrying.
If it still appears to loop:
- Confirm the edited files live under the watched app source root.
- Check whether another tool is rewriting Swift files repeatedly.
- Restart
watch, then rerunsnapview doctor --scheme MyAppto look for drift that is not tied to file mtimes.
Typical symptom:
- You create helper preview stores in a shared fixture namespace, and Swift 6 rejects a
Store(...)call with actor-isolation or non-Sendable errors.
Cause:
Storeinitialization is@MainActor.- A shared preview helper was created in a nonisolated context.
How to fix:
- Put the preview fixture namespace or helper on the main actor.
Example:
@MainActor
enum MyPreviewData {
static func inertStore<State, Action>(initialState: State) -> Store<State, Action> {
Store(initialState: initialState) {
Reduce<State, Action> { _, _ in .none }
}
}
}This keeps preview-only store construction deterministic and Swift 6-safe.
Typical symptom:
- SwiftUI crashes while rendering previews that use
NavigationStackor require a real UIKit hosting environment.
What snapview does now:
- The generated renderer snapshots through an offscreen
UIWindowSceneandUIHostingController, not a bareImageRendererpath.
What to do if you still see a crash:
- Verify the screen renders in Xcode previews first.
- Reduce the preview to the smallest crashing case.
- Confirm the crash is in the app view code, not in test-target setup or stale host artifacts.
- Rerun
snapview prepare, restart the host, and try again.
When an external app project does not render correctly:
- Run
snapview doctor --scheme <Scheme>. - Run
snapview listand confirm the screen is actually covered by#Preview. - Ensure the test target has a generated or real
Info.plist. - Run
snapview watch --scheme <Scheme>for the normal local loop, orsnapview prepare --scheme <Scheme>if you are staying on explicit primitives. - Restart the persistent host if you are using manual host commands and it was already running.
- Run
snapview render-all --scheme <Scheme>if you need an explicit full refresh outsidewatch. - If
.snapviewis not writable, use the runtime output path reported by the command or the paths embedded ingallery.html.