Fix SwiftGen Generated Files Not Updating in Xcode

When SwiftGen's generated Swift files stop reflecting your assets or strings, the cause is usually stale build-phase file lists, wrong config paths, or caching. Here are the fixes in order.

Recognizing the Symptom

The symptom is that you add, rename, or delete a resource — an image, a color, a localized string — but the generated Swift symbols do not change to match. You might reference a newly added asset and get an unknown-member compile error, or delete an asset and find its stale symbol still present, or rename something and see the old name persist. Because the generated file looks like ordinary source, it is easy to assume SwiftGen is broken when in fact it simply did not run, ran against the wrong inputs, or ran and Xcode used a cached copy. The key diagnostic question is whether SwiftGen executed at all for this build and, if it did, whether it read the resources you actually changed and wrote to the file the compiler is reading. Work through that chain — did it run, did it read the right inputs, did it write the right output, did Xcode pick up the new output — and the cause becomes clear. The following sections cover each link in that chain in order of how often it is the culprit. Resisting the urge to guess and instead following the chain in order is what turns a frustrating, intermittent problem into a five-minute fix.

Cause 1: Build-Phase Input/Output Files Skipping Runs

If you declared Input Files and Output Files on your SwiftGen Run Script build phase to speed up incremental builds, Xcode uses them to decide whether to run the phase. When those lists are wrong or incomplete, Xcode skips SwiftGen even though a resource changed, leaving stale output. The most common mistake is omitting an input — for example listing only your .xcassets but not your .strings files, so string changes never trigger regeneration. Another is an input path that does not match where the resource actually lives, so Xcode never detects the change. Review the phase's Input Files list and confirm every resource SwiftGen parses is represented, and that the Output Files list names every generated file. If you recently added a new parser to swiftgen.yml but did not update these lists, that new parser's inputs are invisible to Xcode's up-to-date check. As a quick test, temporarily remove the input/output lists so the phase runs unconditionally; if the files then update correctly, you have confirmed the lists were the problem and can fix them precisely. Once you have restored correct lists, verify them by touching each kind of resource in turn and confirming a build regenerates, which proves every input is actually tracked rather than just the one you happened to test.

Cause 2: SwiftGen Is Not Running at All

Before blaming file lists, confirm SwiftGen actually executes during your build. If you generate manually and forgot to run swiftgen config run after changing a resource, the output is simply stale by design — run it and the files update. If you expect a build phase or SPM plugin to run it, check the build log in Xcode's report navigator to see whether the SwiftGen phase appears and completes. A phase that errors early — for instance failing with command not found because of a PATH issue — will not update files, and the error may be easy to miss in a long log. A phase positioned after Compile Sources runs too late to affect the current compile. Also confirm you are building the target that actually contains the phase. Run generation directly from Terminal with swiftgen config run to see whether the tool itself produces updated output; if the terminal run updates the files but the build does not, the problem is in your build integration, not in SwiftGen or your config. Establishing whether the tool ran is the fastest way to narrow the cause. When you read the build log, search it for the phase's name so you can see not only that it ran but also whether it exited successfully or printed a warning you would otherwise scroll past.

Cause 3: Wrong Config or Path Resolution

SwiftGen resolves inputs and outputs relative to the configuration file, or relative to input_dir and output_dir if you set them. If those paths are wrong, SwiftGen may read an old resource location or write the generated file somewhere the compiler never looks — so it appears not to update even though it ran successfully. Open your swiftgen.yml and trace each parser's inputs and outputs against the real file locations. A frequent mistake is editing resources in one folder while the config points at a copy or an outdated path. Another is writing the output to a path that is not the file included in your Xcode target, so the target keeps compiling a different, stale file. Confirm the output path in the config is exactly the file added to your target's Compile Sources. If you pass --config with an explicit path in a build phase, make sure it points at the config you are actually editing, not a stray duplicate. Correcting the path resolution so SwiftGen reads your live resources and writes the file the compiler consumes resolves this class of problem. Duplicate configuration files are a surprisingly common trap in larger repositories, so if a project has more than one swiftgen.yml, confirm which one the build actually invokes before spending time editing the wrong file.

Cause 4: Xcode Caching and Derived Data

Occasionally SwiftGen runs and writes the correct file, but Xcode continues compiling a cached version, so your changes seem to vanish. This is less common than misconfigured file lists but does happen, especially after aggressive branch switching or when the generated file's timestamps confuse the build system. The standard remedy is to clean the build folder with Product then Clean Build Folder (hold Option to reveal it), and if that is not enough, remove the project's Derived Data and rebuild. Do this only after confirming the file on disk actually contains your changes — open the generated file in an editor and verify the new symbol is present. If the file on disk is correct but the build still uses old symbols, caching is the likely culprit and a clean build resolves it. If the file on disk is itself stale, caching is not the issue and you should return to the earlier causes. Treat a clean build as a diagnostic step that separates a generation problem from a build-system caching problem, not as a routine fix to apply blindly. Reaching for a clean build first, before checking whether the on-disk file is even correct, is the classic way to waste time on a problem that a wrong config path was actually causing.

Cause 5: Generated File Not in the Target

A subtle cause is that SwiftGen correctly generates and updates the file on disk, but the file is not a member of the target you are building, so the compiler never sees the new symbols. This happens when a generated file exists in the file system but was never added to the Xcode project, or was added to a different target. Check the generated file's Target Membership in the File Inspector and confirm it belongs to the target that references the symbols. If you generate into a folder and rely on a folder reference, make sure new files created by SwiftGen are actually picked up rather than sitting outside the build. When generated files are git-ignored and produced at build time, ensure the build phase writes them into a location already included by the target, or that your project uses a synced group that captures them. The generated symbols only become available to compile once the file is genuinely part of the target, so verifying membership closes the gap between a correct on-disk file and code that will not compile against it. This cause is especially easy to miss right after adding a brand-new parser whose output file has never been added to the project, since the earlier, already-tracked generated files keep updating normally while the new one silently never joins the build.

A Reliable Diagnostic Order

To fix this efficiently, follow the chain rather than guessing. First, run swiftgen config run directly in Terminal and open the generated file — if the symbols are now correct there, SwiftGen and your config are fine and the problem is in build integration or caching. If the terminal run does not update the file, inspect swiftgen.yml paths and the config you are actually invoking. Once the on-disk file is correct, confirm the build runs SwiftGen by checking the report navigator, then verify the build-phase input/output lists include every changed resource. Finally, confirm the generated file is a member of the target and, if all else looks right, clean the build folder to rule out caching. Working in this order — tool, config, execution, file lists, membership, cache — isolates the cause quickly instead of applying random fixes. To prevent recurrence, keep input/output file lists in sync with swiftgen.yml whenever you add a parser, and document whether generated files are committed or produced at build time so contributors understand how updates are expected to flow. Writing this diagnostic order into your project's troubleshooting notes means the next person who hits stale output solves it in minutes rather than rediscovering the whole chain from scratch.

Frequently Asked Questions

Why does SwiftGen skip regenerating when I change a resource?

If your build phase declares Input Files and Output Files, Xcode skips the phase when the changed resource is not listed. Add every resource SwiftGen parses to Input Files and every generated file to Output Files.

How do I confirm SwiftGen actually ran during the build?

Open Xcode's report navigator and check the build log for the SwiftGen phase. If it does not appear or errored early, it did not update files. Running swiftgen config run in Terminal confirms the tool itself works.

My generated file on disk is correct but the build uses old symbols. Why?

This is usually Xcode caching. Clean the build folder with Product then Clean Build Folder, and if needed remove Derived Data, then rebuild. Only do this after verifying the on-disk file contains your changes.

Why does SwiftGen write a file the compiler never sees?

The output path in swiftgen.yml may not match the file added to your target, or the generated file is not a member of the target. Confirm the output path and the file's Target Membership match the target you build.

I added a new parser and only its output is stale. What happened?

You likely did not update the build-phase Input Files and Output Files after adding the parser, so Xcode's up-to-date check ignores the new resources. Add the new inputs and outputs to those lists.

What is the fastest way to isolate this problem?

Run swiftgen config run in Terminal and inspect the generated file. If it is correct there, the issue is build integration or caching; if not, the issue is your config paths or invocation.