D
P
0

Shopify & Liquid

Shopify Theme Upload Rejected With `theme_author too long` and `default can't be blank`? Hidden Schema Limits Surface at Push

July 6, 2026·4 min read
Shopify Theme Upload Rejected With `theme_author too long` and `default can't be blank`? Hidden Schema Limits Surface at Push

I was shipping about 13 new sections to a client store's Shopify theme. Everything ran fine locally, so the only thing left was shopify theme dev to push to the development store and see it live. I expected a single verification pass. What I got was a queue of schema rejections that arrived one at a time, like being skinned slowly.

First refresh: upload rejected, theme_author too long. I fixed it, refreshed again. Now invalid range step in a different section. Fixed, refreshed. Now default can't be blank. Fixed, refreshed. default can't be blank again, on a different setting. Then an apostrophe-escaping error in a Liquid string. Each fix only unlocked the next error, because the dev server stops at the first violation it finds and never shows the rest at once.

Why the errors surface one at a time

The frustrating part was not the errors themselves, it was the rhythm. settings_schema.json and per-section schemas enforce a set of hard caps that are not checked locally and only surface at upload. The dev server validates the schema when you push, fails on the first rule you break, and stops. So if you have five violations, you need five refresh cycles to find them all. No linter in my editor caught any of this ahead of time.

The limits that bit me, none of which look wrong while you write the schema:

  • theme_author must be at most 25 characters. Mine read like Studio Name (WeAreBrand), which is 28 characters, so it was rejected.
  • A range control must satisfy (max - min) / step + 1 <= 101 discrete steps. I had written a pill-radius range with min 0, max 999, step 1, which is 1000 steps, far over the 101 cap.
  • text, textarea, and richtext settings reject "default": "". An empty schema default is treated as invalid. Not ignored, flatly rejected.
  • A Liquid string with an apostrophe I escaped as '\'' choked the parser.

None of these read like a bug as you type them. A range from 0 to 999 is reasonable. An author string with the studio name is reasonable. "default": "" looks like a polite way of saying "no initial value". But Shopify's schema validator disagrees, and it only tells you so one error at a time.

The fix: sweep the schema before pushing

The real lesson was not how to fix each individual error, it was to stop discovering them reactively. Now I run a pre-flight sweep across the whole schema before pushing, so every violation surfaces at once instead of one per refresh.

For theme_author, I just shorten it to 25 characters or fewer. For every range, I compute (max - min) / step + 1 and confirm the result is <= 101. I changed the pill radius from max 999 to max 100:

{
  "type": "range",
  "id": "pill_radius",
  "label": "Pill radius",
  "min": 0,
  "max": 100,
  "step": 1,
  "unit": "px",
  "default": 8
}

With min 0, max 100, step 1 that is (100 - 0) / 1 + 1 = 101 steps, right at the cap. The earlier 0..999 range produced 1000 steps, which is exactly what triggered invalid range step.

For blank defaults, I grep every .liquid and .json file for empty default strings, then fill or remove them:

grep -rn '"default": *""' sections/ snippets/ config/

The rule I hold to: if a text, textarea, or richtext setting has no sensible initial value, I drop the default key entirely. Omitting the default key means "no default", and that is valid. Writing it as "default": "" is not.

One important trap to keep separate: empty values inside templates/*.json files are fine. Those fields are not schema defaults, they are values a user filled in via the theme editor, so a blank there is legitimate and is not what rejects the upload. The strict validation is on schema defaults, not on template values.

For escaping apostrophes in Liquid strings, I stopped using the '\'' trick. If a string needs an apostrophe, I wrap it in double quotes:

{{ "don't show this again" }}

Using "don't" with double quotes is far cleaner than picking apart an apostrophe inside single quotes.

The pre-flight schema checklist

Before pushing a theme with many new sections, I now sweep first:

  • Compute (max - min) / step + 1 for EVERY range and confirm it is <= 101. If it overflows, raise step or lower max.
  • Check theme_author in settings_schema.json is at most 25 characters.
  • Grep "default": *"" across all .liquid and .json, then remove the key or fill the value. Remember: blank defaults are only a problem in schemas, not in templates/*.json.
  • Apostrophes in Liquid strings, wrap in double quotes rather than escaping inside single quotes.

The Shopify dev server will keep surfacing problems one at a time if you let it. The trick is not to hand that job to the dev server. Every one of these limits can be computed from the local files before a single byte is sent, and a five-minute sweep saves fifteen painful refreshes.