I’ve been thinking about a FileMaker 2026 feature ever since I caught a livestream with Honza Koudelka of 24U Software and Vince Menanno of Beezwax in June. They were running through their favorite features in the new release, and the conversation turned to the new Save-as-XML and Upgrade Tool workflow. The part that stuck with me wasn’t the deployment-automation angle but an aside in that stretch of the discussion: Vince and Honza speculated that if you can serialize a .fmp12 out to XML and then rebuild a brand-new file from it, you might be able to clean up and validate a file that had previously been recovered. That’s the thread I was pondering.
The mechanism is the –generateDBFile argument to the FileMaker Upgrade Tool, which is new in 2026. It’s described in the FileMaker 2026 release notes, with the command-line details in the Upgrade Tool Guide. The headline use case is version control and CI/CD. The use case I care about is older and more superstitious.
Anyone who has run a big solution for years (or inherited one, as we often do) knows the worry. A file can pass a consistency check and open every morning and still carry damage from somewhere back in its history. The usual tool for that is Recover, but Recover copies your existing structure forward, and Claris is explicit that a recovered file should not go back into production. The documented best practice is to treat a recovered file only as a source: import its data into a fresh clone that has never itself been recovered, and run on that.
That’s the rule. The reality is messier. A great many solutions in everyday use have been recovered at some point in their history and simply kept running because rebuilding a clean file by hand is expensive, and the recovered file seemed fine.
That gap is what makes this feature interesting. If –generateDBFile builds a new file from a structural description instead of copying old blocks forward, it raises the tantalizing possibility of a path back to a known, clean, validated file for a solution that drifted from that ideal years ago. That would not be a repair. It would be a rebuild. Does it actually deliver? That is what I wanted to test.
So I did. I tested it on fifteen real files, and here’s what I found.
The promise holds on small files.
I started where everyone starts: with a tiny demo file. I took an XML export, ran FMUpgradeTool –generateDBFile against it, and got a fresh .fmp12. Clean consistency check, zero bad blocks, every node rebuilt. Then I did the obvious next thing: exported that generated file back to XML and diffed it against my original.
They’re not identical, and I think the differences make sense. Every object UUID gets regenerated. The binary chunks get re-packed and re-deduplicated from scratch. The catalogs are rebuilt node by node rather than copied. Custom functions and scripts came through byte-for-byte, but the file’s internal identity and block layout were built fresh from the specification. In other words, the tool isn’t so much cloning your file as reconstituting one from a description. If you’re hoping to shed invisible corruption, it seems possible this method could do it. I wouldn’t go further than that on a small file.
Then I fed it a real solution.
The next test subject was a genuine production solution: 188 base tables, 1,493 layouts, 1,307 scripts. The XML export weighs in at 235 MB and 5 million lines—the kind of big, mature, years-of-edits file I wanted to see this tool struggle with.
Unfortunately, it did struggle. About four and a half minutes in, the tool died with exit code 139, a segmentation fault. No “…is generated!” line, no summary in the log.
The tricky part is what it leaves behind. The tool still writes a .fmp12, and that file passes a consistency check cleanly: 18,963 blocks, zero bad blocks. Looks healthy, but it’s not. When I re-exported and counted, the schema and code were all present, but the layouts had gone from 1,493 to 232. Eighty-five percent of the layouts simply weren’t there.
If you use this tool, check the result logs carefully.
The theory that fooled me.

It would be nice to narrow down what causes a file to fail. I spent a good while looking into this, and the wrong turns are worth keeping in, since a theory that fell apart tells you more than one I’d quietly cleaned up after the fact.
It isn’t file size: a 32 MB file crashed harder than the 235 MB one.
It isn’t layout count: the file with the fewest layouts lost all of them.
For about six files, script count looked like the answer. Sort the files by number of scripts and the survivors fell in a perfect staircase. There was even a plausible mechanism, since the script catalog is rebuilt before the layouts and never seems to hand its memory back. I was ready to write “watch your script count.”
Then a small file with just 74 scripts seg faulted at two layouts, while its 248-script sibling rebuilt cleanly. So, the script count was a spurious correlation — six mature files that happened to be heavy in every dimension at once. One file that didn’t fit the mold disproved the theory.
Eleven files in, the honest answer is that I cannot predict from the outside which solutions will survive. Not by size, not by layout count, not by script count, not by how heavy the layouts are.
What I can say is narrower: a given file crashes at the same spot every time, and when I delete the object it dies on, the crash moves to the next one. Big old solutions just contain more chances to hit whatever the trigger might be.
The four ways it failed for me.
Across fifteen files, the failures sorted into four buckets:
- Silent segfault inside the layout rebuild. Exit 139, partway through the layout catalog. No summary line in the log. Leaves a partial .fmp12 that passes the consistency check but is missing some or all of its layouts.
- Node-ID conflict. The rebuild hits duplicate internal IDs in the binary library and stops before the layout stage, but it completes the program normally and prints Nodes failed: 796 plus an explicit WARNING: …do NOT use this generated FMP12 file. A good honest failure, as it tells you to your face.
- Malformed XML, rejected outright. One file’s export contained a raw control byte inside a CDATA section — illegal XML even there — and the parser refused the whole document. Worth knowing the export side can emit XML that the import side won’t accept.
- Clean. Exit 0, all layouts present, consistency clean. Every one of these was on the smaller, simpler, well-factored end.
Here’s the full ledger, all fifteen files. “Layouts out” is how many layouts survived into the rebuilt file. (Client solutions are anonymized.)
| # | File (anonymized) | XML size | Tables | Layouts | Scripts | Result | Layouts out | Crash time |
|---|---|---|---|---|---|---|---|---|
| 1 | Demo (FM_Favorites) | 1.1 MB | 2 | 5 | 8 | clean | 5 / 5 | — |
| 2 | Mid-Clean | 74 MB | 68 | 279 | 642 | clean | 279 / 279 | — |
| 3 | Monolith | 235 MB | 188 | 1,493 | 1,307 | segfault | 232 / 1,493 | ~4m 20s |
| 4 | Tracker | 55 MB | 86 | 282 | 1,655 | segfault | 33 / 282 | ~8s |
| 5 | FieldOps | 95 MB | 125 | 483 | 1,685 | bad-XML, then segfault | 3 / 483 | ~38s |
| 6 | Commerce | 32 MB | 34 | 120 | 3,557 | segfault | 0 / 120 | ~4s |
| 7 | Clinic-Patients | 84 MB | 40 | 387 | 3,179 | node-ID conflict | 0 / 387 | (aborts) |
| 8 | Clinic-Inquiries | 22 MB | 9 | 88 | 437 | node-ID conflict | 0 / 88 | (aborts) |
| 9 | Clinic-Pivot | 3.2 MB | 8 | 22 | 74 | segfault | 2 / 22 | ~3s |
| 10 | Clinic-Batch | 5.2 MB | 8 | 60 | 248 | clean | 60 / 60 | — |
| 11 | Clinic-Env | 0.3 MB | 2 | 2 | 4 | clean | 2 / 2 | — |
| 12 | Referral-Client | 15 MB | 7 | 77 | 119 | clean | 77 / 77 | — |
| 13 | Referral-Doctor | 0.5 MB | 1 | 3 | 3 | clean | 3 / 3 | — |
| 14 | Referral-Eligibility | 1.5 MB | 8 | 17 | 15 | clean | 17 / 17 | — |
| 15 | Referral-Prospect | 3.8 MB | 9 | 26 | 65 | clean | 26 / 26 | — |
And the same fifteen runs, summarized by outcome:
| Outcome | Files | What you see | Layouts lost |
|---|---|---|---|
| Clean rebuild | 8 of 15 | Exit 0, “Nodes failed: 0”, all layouts present | None |
| Silent segfault | 5 of 15 | Exit 139, no summary line; partial file still passes the consistency check | Some to all |
| Node-ID conflict | 2 of 15 | Exit 0 but “Nodes failed” > 0 with an explicit warning | All |
Final tally across all fifteen: eight clean, seven broken. (One of the segfaults, FieldOps, also failed to parse on its first pass because of a stray control byte in the source XML — the malformed-XML failure mode — and segfaulted only after I cleaned that byte out.)
Could this double as a troubleshooting tool?
There’s a flip side to all this breakage that I think has value. Some of what stopped the rebuild wasn’t a bug in the tool — it was the tool catching a genuine defect in my file that nothing else had flagged. The duplicate internal IDs that aborted two of the rebuilds are real, and they had passed consistency checks. So had the stray control character, a raw 0x10 byte sitting in a PopOver button’s label, illegal in XML even inside a CDATA section, which one solution had apparently been carrying around invisibly for who knows how long.
This result makes me wonder whether generateDBFile could earn its keep as a troubleshooting tool, quite apart from rebuilding anything. It seems possible to me that on a file with difficult-to-explain problems, you could run the tool, read what it chokes on, fix that one defect in the source, and run it again, working through the gremlins one at a time until it comes out clean. The loud failures cooperate with that: the node-ID conflict names itself in the log, and the XML parser points right at the bad byte.
The silent segfaults are less helpful, since they don’t tell you what they hit and leave you dissecting by hand, the way I had to (well, the way I instructed the AI model to). So it could be a partial diagnostic tool. I certainly plan to fix that gremlin character in the button label now that I know it’s there.
How should you use this tool?

Carefully, and never on faith. The rule that matters: trust the generate log, not the file, and not the consistency check.
- Confirm the log shows Nodes succeeded: N. Nodes failed: 0. A missing summary line means a silent crash; a non-zero Nodes failed means a conflict abort. Either way, stop.
- Read the log for any WARNING: line.
- Re-export the rebuilt file and diff the layout, script, table, and value-list counts against the source.
- Re-set the File Access “require full access privileges” flag afterward — the tool doesn’t seem to reliably preserve it.
- Sanity-check the source XML for stray control characters before you start.
And don’t overlook the second way to use it: as a diagnostic. Every file it choked on, it choked on for a reason which no consistency check had ever surfaced — a duplicate internal ID, an illegal character in a label. On a file with problems you can’t otherwise explain, run it and read what it complains about.
Bottom Line
Back to the question that started this: could generateDBFile get a recovered, drifted-from-clean solution back to a known good file? In FileMaker 26.0.1, the answer is not yet — except for the files that least need it. It rebuilt the tidy, modestly-sized, well-factored files in my set cleanly, every count matching and every layout present.
On the big, mature solutions most likely to carry an old recovery in their past, it failed more often than it succeeded across my fifteen files. The most common failure was the dangerous kind: Silent, and passed by the consistency check.
That’s the state of it today. It’s also the first release of an ambitious capability, and the direction is one I’m glad to see — serialize a solution to text, rebuild it from spec, and bring real version control and CI/CD to the FileMaker platform.
It seems to work well for small, well-structured files. The failures I hit were consistent and repeatable, which should help whoever has to track them down; I won’t guess at the cause or about when they’ll be addressed. I’ve kept all fifteen files, and I’ll re-run them when an update lands. I’ll keep the AI session history on for this experiment so that it’s easy to re-run my analysis.
The tantalizing version of this project — a dependable way to bring a recovered file back to a clean, validated state — isn’t here yet. But nothing I saw says it can’t get there!
Thanks to Honza Koudelka (24U Software) and Vince Menanno (Beezwax) for sending me down this path.
– John Newhoff
This piece represents a collaboration between the human authors and AI technologies, which assisted in both drafting and refinement. The authors maintain full responsibility for the final content.
