Serialized Data Fixer
Repair a PHP serialized value whose string lengths no longer match its contents.
What this tool does
WordPress keeps arrays and objects in the database as PHP serialize() output, a format that writes the byte length in front of every string — s:5:"hello". Run a plain SQL REPLACE() across the tables and the text changes while those numbers stay as they were, so unserialize() refuses the value and the row reads back as empty. That is why widgets disappear, menus empty out and theme settings return to their defaults after a domain change, even though the data is still sitting in the table exactly where you left it.
Serialized Data Fixer parses the value with those declared lengths treated as hints rather than facts. It works out where each string really ends by looking for a terminator that leaves valid data behind it, then writes the correct UTF-8 byte length back — bytes, not characters, which is what PHP counts and what catches people out on accented titles and emoji. Array and object element counts are recounted the same way, so a list that gained or lost an entry declares the right number again. Floats keep their exact printed text, reference markers are copied through untouched, and running the tool on a value that was already sound returns it unchanged and says so.
There are two outputs. Repaired serialized data is what you paste back into option_value or meta_value; readable JSON is there when you only want to see what a plugin has actually stored. The optional find and replace rewrites string values inside the parsed structure and recomputes the byte count of every string it touches, so a flat option survives a domain or upload-path swap that a SQL REPLACE() would have wrecked — with one exception, set out below, for a string that is itself serialized data. If the text came out of a mysqldump with escaped quotes and backslashes, tick the SQL dump box before running. Everything happens in this browser tab: database contents are not uploaded, and the page works with the network off.
The limits matter more than the feature list. One value per run — anything after the end of the first value is refused, so a dump or a column of rows has to be done a row at a time. Only the standard markers are understood: s, a, O, i, d, b, N and references. A class that implements Serializable (C:) or a backed enum (E:) is reported as an unrecognised value rather than repaired. Find and replace touches string values only, never array keys or class names. The JSON view is one-way — objects gain a __class__ key and references become placeholder text, so it reads well but cannot be pasted back. And where a string genuinely contains the terminator sequence, the end is chosen by scanning forward for a quote-and-semicolon whose next few characters begin like another marker, preferring the candidate whose byte count matches the declared length and otherwise taking the earliest one — a heuristic that can pick wrong.
Double serialization is the limit to check before you trust an output. Plugins and postmeta rows routinely keep one serialize() result inside another as a string, and every string here is treated as opaque text, so the nested layer is never entered. If that inner data holds a string of its own, a broken value cannot be repaired at all: the first terminator inside the nesting is taken for the end of the outer string and the run stops with a position complaint. On a nested value that is still sound, find and replace produces the very fault this page is about — the outer length is rewritten correctly while the inner s: counts keep their old totals — and running the tool again on that output reports that nothing was broken, because it cannot see inside a string. For anything nested, unserialize it in PHP or let WP-CLI search-replace walk the levels.
How to use it
- Paste one serialized value. Copy the whole option_value, meta_value or postmeta field, including the trailing semicolon. Load sample shows the shape it expects if you want to try it first.
- Say where it came from. Tick the SQL dump box when the text carries \" and \\ escapes from mysqldump, so those are removed before parsing rather than counted as content.
- Choose the output. Repaired serialized data to paste back, or readable JSON to inspect what the row holds without touching the database at all.
- Add a find and replace if you need one. Type the old domain or path and its replacement. Only string values are changed, and every affected length is recalculated afterwards.
- Read the summary, then copy. It reports how many string lengths and element counts were corrected. Those figures cover the lengths the parser can see, and never any held inside a nested serialized string.
Processing & privacy
Runs on your device. Your file is processed directly in this browser.
Common use cases
Widgets vanished after a domain change
A broken option makes the widget array unreadable, so the sidebar renders empty. Repairing the lengths brings the stored layout back without rebuilding it.
Customiser settings reset themselves
theme_mods_yourtheme is one serialized array. When its byte counts stop matching, the theme falls back to defaults and every colour and logo choice appears lost.
Seeing what a plugin actually stores
Switch the output to JSON and the option becomes a readable structure, which is quicker than reading a single line of s: and i: markers.
Swapping a URL inside one row
Use find and replace here instead of SQL REPLACE(). Each edited string has its length rewritten with the text, so a flat row comes back loadable — check first that no value in it is itself serialized, because those are left with stale inner counts.
An accented title broke the row
PHP counts bytes, so Café is five bytes and not four. Anything that recounted characters produces a value that will not unserialize until the byte length is restored.
Questions
Why does a search-and-replace break WordPress?
Is my database content uploaded?
Can I paste a whole SQL dump or a full table?
Should I use this for a whole site migration?
Does it cope with accented characters and emoji?
Can I turn the JSON back into serialized data?
What if it refuses to parse my value?
Does it fix a value that was serialized twice over?
Related tools
- Meta Tag Preview — See how your title and description look in search results.
- Salt Key Generator — Produce a new set of WordPress authentication salts.
- wp-config Generator — Generate a wp-config.php with fresh security salts.
- .htaccess Generator — Build common Apache rules for WordPress.
- Shortcode Builder — Assemble shortcodes with attributes correctly quoted.
- Theme Header Generator — Create a valid style.css theme header block.