Percentage Wrong After Sync: Why 50% Became 5000%
A percentage comes out 100 times too large or too small after a sync because systems store percentages in two incompatible conventions and no field says which one it uses. HubSpot, Airtable, Google Sheets, and Salesforce formulas store 50% as the fraction 0.5, while Salesforce percent fields and Stripe's percent_off store it as the points value 50. The fix is to declare the convention for every percentage field in the field map and convert by that declaration at each hop, never by guessing from the size of the number.
When a percentage shows up 100 times too large or 100 times too small after a sync, the number did not get corrupted. It got reinterpreted. Systems store percentages in two incompatible conventions: as a fraction, where 50% is 0.5, or as points, where 50% is 50. HubSpot, Airtable, and Google Sheets use fractions. Salesforce percent fields and Stripe's coupon API use points. No field declares which one it uses, so a sync copies the number faithfully and the receiver reads it in its own convention. The fix is to write the convention down for every percentage field and convert by that declaration at each hop, not by guessing from how big the number looks.
Two conventions, and the number never says which
A percentage has no unit on the wire. The payload says "discount": 15, and whether that means fifteen percent or fifteen hundred percent depends entirely on the system that reads it. The field is labeled "Percent" in both places, the sync mapping looks correct, and the test record passes if you happened to test with 0%, the one value both conventions agree on.
This is why the error is always a clean factor of 100. It is the tell. A number that is off by 3 percent is a rounding or a calculation problem, the family we covered in totals that are off by a penny. A number that is off by exactly 100 in one direction is a convention mismatch, and you can stop debugging the math.
Which direction it goes tells you which way the mismatch runs:
- Points into a fraction field gives you the loud one. A commission rate of 12 lands in HubSpot and displays as 1200%. Someone notices on the first record, and the ticket says "50% became 5000%."
- A fraction into a points field gives you the quiet one. A discount of 0.15 lands in a points field and displays as 0.15%. That is a plausible number. It goes out on quotes and coupons, and nobody notices until margin reports look odd or a customer asks why their 15% discount saved them eleven cents.
The quiet direction is the expensive one, because every system in the chain accepts the value as valid.
Which systems store 0.5 and which store 50
Each row below was checked against the vendor's current documentation in September 2026. The column that matters is the second one. The third is where the surprises live.
| System | 50% is stored as | Watch for |
|---|---|---|
| HubSpot percentage property | 0.5 | Documented plainly: "75% is stored as .75." Any source that sends points displays 100 times too high. |
| Airtable percent field | 0.5 | The field model gives the example that "the underlying cell value for 12.3% is 0.123." Precision settings (0 to 8 digits) change display only. |
| Google Sheets, percent format | 0.5 | The format multiplies by 100 only when rendering. A formatted read returns the text "50%", an unformatted read returns 0.5. |
| Salesforce percent field | 50 | Record values move as points. In our experience the API returns Opportunity Probability as 50.0 for 50%. |
| Salesforce formula referencing a percent field | 0.5 | The same field is divided by 100 inside a formula. Save the result back without converting and 100% becomes 1%. |
Stripe coupon percent_off | 50 | Must be "larger than 0, and smaller or equal to 100." A fraction such as 0.15 is accepted and creates a 0.15% coupon. |
| AI extraction step | Whatever the model chose | "15% off" comes back as 15 on one run and 0.15 on another unless the schema says which. |
Two rows deserve more than a table cell.
Salesforce disagrees with itself. Its knowledge article on percentage fields in flows describes both behaviors side by side. Assign a percent field directly from one record to another and "100 remains 100," saved as 100%. Reference that field inside a formula and it divides by 100, so "100 becomes 1," and saving that formula result to a percent field produces 1%. So a flow that computes a blended rate with a formula and writes it to a percent field is a fraction-to-points hop that happens entirely inside one product. Nobody looks for a convention mismatch inside a single system, which is exactly why it survives review.
Google Sheets has a third convention: text. Typing 50% into a cell stores 0.5 and the percent format renders it back. When an automation reads the sheet, the Sheets API gives it a choice. FORMATTED_VALUE returns values "formatted in the response according to the cell's formatting," which means the string "50%". UNFORMATTED_VALUE returns the stored 0.5. n8n's Google Sheets node defaults to unformatted, which keeps the number type, and its formatted option explicitly converts "the data type from number to string." Writes have the same fork: USER_ENTERED parses strings "as if the user typed them into the UI," so writing "50%" stores 0.5, while RAW stores the text as-is. A sheet sitting between two systems, which is how a lot of syncs start life (we covered when a sheet is a fair backend), can emit a fraction, a formatted string, or a number depending on two settings nobody remembers choosing.
The fix that makes it worse: guessing from magnitude
The first fix most people write is a heuristic: if the value is greater than 1, it must be points, so divide by 100. It clears the ticket. It also corrupts every legitimate value on the wrong side of 1.
A year-over-year growth rate of 150% is 1.5 as a fraction. The heuristic reads it as 1.5 percent and leaves it alone, so it lands in a points field as 1.5%. A payment processing fee of 0.75% stored as points is 0.75, which is under 1, so the heuristic treats it as a fraction and turns it into 75%. Interest rates, commission splits under one percent, and anything that can exceed 100 all live in the zone where the guess fails, and they fail silently because the output is still a plausible number.
The magnitude of a percentage tells you nothing about its convention. Only the field definition does. We hold that position firmly, because the heuristic is the most common "fix" we find in inherited workflows, and it usually has a second heuristic stacked on top of it for the case the first one broke.
Rounding has the same trap one level down. Massachusetts sales tax is 6.25%, which is 0.0625 as a fraction. A step that rounds to two decimal places, a habit carried over from currency, turns it into 0.06, which is 6%. Rounding to two places is harmless in points and destructive in fractions. Round only after converting to the receiver's convention, and only to the precision the receiver displays.
Declare the convention, convert by declaration
The durable fix is boring, and it holds up across every tool pair we have wired.
- Add a convention column to the field map. For every percentage field on both sides of every sync, record one of three values: fraction, points, or text. If your field map is a spreadsheet, it is one new column. If you do not have a field map, this is a good reason to start one, because the same column will catch the next unit problem too.
- Convert at the hop, from the declaration. Fraction to points multiplies by 100. Points to fraction divides by 100. Text parses the number, strips the percent sign, and then treats the result as points. Nothing inspects the value to decide which branch to take.
- Read spreadsheets unformatted. Pull numbers, not display strings, and write with a mode you chose deliberately. If a connector only offers formatted values, parse at the read step so a string never reaches a numeric field.
- Name the convention in AI schemas. An extraction schema field called
discountinvites the model to pick. A field calleddiscount_percent_pointswith the description "15 means 15 percent" does not. Pair it with the range checks from verifying AI document extraction so a value outside the plausible range goes to review instead of into a quote. - Guard the range per field. A discount is between 0 and 100 points. A win probability is between 0 and 1 as a fraction. A value outside the declared range stops the record and logs both the raw and converted value, the same raw-versus-written pair we recommend in what to log in every automation. This is what catches the quiet direction.
Then test with a value that cannot pass by accident. Not 0, not 100, not 50. Use 12.5%. Push it through the whole chain and check that every receiver displays 12.5%. A wrong convention shows up as 1250% or 0.125%, and a stray rounding step shows up as 12% or 13%. One test record, one look per system, and it exercises both directions and the rounding trap at once.
What to do next
Open the field map for your busiest sync and search it for every field whose name contains percent, rate, probability, discount, margin, or commission. For each one, write down the convention on both sides. In most stacks we audit, at least one pair disagrees, and the disagreement has been converted by a magnitude guess that has not failed loudly yet. The same field-by-field discipline is what keeps phone numbers intact across systems, and it is the core of the data intelligence platforms we build, where every field carries its type, unit, and convention alongside its value. If your syncs cross more systems than you can audit by hand, tell us what is connected and we will map the conventions with you.
Frequently Asked Questions
SOURCES & CITATIONS
- Understand property field types in HubSpot — HubSpothttps://knowledge.hubspot.com/properties/property-field-types-in-hubspot
- Field model (Percent field type) — Airtablehttps://airtable.com/developers/web/api/field-model
- Understanding Salesforce Percentage Fields in Flows (Knowledge Article 000380436) — Salesforcehttps://help.salesforce.com/s/articleView?id=000380436&language=en_US&type=1
- Create a coupon (percent_off) — Stripehttps://docs.stripe.com/api/coupons/create
About Alexey Yushkin
Alexey is the founder of GENERAL INFORMATICS LLC. He designs and ships AI and automation systems for businesses and operators across the US.
Related reading
Want this kind of system in your business?
We build practical AI and automation systems for operators. Send us your current workflow and we will show you what to automate first.
