← back to Designer Wallcoverings
Handle Shopify DAILY variant-creation cap (the real blocker)
8ed26702e9773178701d89d1be19f447047da593 · 2026-06-11 15:29:40 -0700 · SteveStudio2
Root cause of the failed creates: VARIANT_THROTTLE_EXCEEDED — a per-day variant-creation
limit (not the GraphQL cost bucket). createProduct now surfaces it (stop:true), the import
bails immediately instead of grinding, schu-reimport exits the tick on detection, and the
launchd retry slowed 5min→hourly. Backfill now spreads across days, resuming as the cap rolls.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Files touched
M shopify/scripts/cadence/cadence-import.jsM shopify/scripts/cadence/schu-reimport.sh
Diff
commit 8ed26702e9773178701d89d1be19f447047da593
Author: SteveStudio2 <stevestudio2@SteveStudio2s-Mac-Studio.local>
Date: Thu Jun 11 15:29:40 2026 -0700
Handle Shopify DAILY variant-creation cap (the real blocker)
Root cause of the failed creates: VARIANT_THROTTLE_EXCEEDED — a per-day variant-creation
limit (not the GraphQL cost bucket). createProduct now surfaces it (stop:true), the import
bails immediately instead of grinding, schu-reimport exits the tick on detection, and the
launchd retry slowed 5min→hourly. Backfill now spreads across days, resuming as the cap rolls.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
---
shopify/scripts/cadence/cadence-import.js | 13 +++++++++----
shopify/scripts/cadence/schu-reimport.sh | 7 ++++++-
2 files changed, 15 insertions(+), 5 deletions(-)
diff --git a/shopify/scripts/cadence/cadence-import.js b/shopify/scripts/cadence/cadence-import.js
index b80cd7f5..3f975306 100644
--- a/shopify/scripts/cadence/cadence-import.js
+++ b/shopify/scripts/cadence/cadence-import.js
@@ -213,13 +213,16 @@ async function createProduct(table, row, payload) {
// dw_unified FIRST
logPriceToDb(table, row.dw_sku, payload.retail);
const r = await gqlRetry(PRODUCTSET, { input: payload.input });
+ // Shopify enforces a DAILY variant-creation cap separate from the GraphQL cost bucket.
+ // When hit, every create fails with VARIANT_THROTTLE_EXCEEDED until the 24h window rolls.
+ // Signal stop:true so the caller bails immediately instead of grinding failed creates.
+ const topErr = r.json && r.json.errors ? JSON.stringify(r.json.errors) : '';
+ if (/VARIANT_THROTTLE_EXCEEDED|Daily variant creation limit/i.test(topErr)) return { ok:false, err:'DAILY_VARIANT_LIMIT', stop:true };
const ue = r.json?.data?.productSet?.userErrors;
if (ue && ue.length) return { ok:false, err: ue };
const pid = r.json?.data?.productSet?.product?.id;
- // CRITICAL: only count as created when a real product id comes back. A throttle-exhausted
- // or empty response has no userErrors AND no pid — previously that was mis-counted as ok,
- // inflating "CREATED N" while nothing was made (and the row stayed net-new → re-run safe).
- if (!pid) return { ok:false, err: r.raw || 'no-pid (throttled/empty response)' };
+ // CRITICAL: only count as created when a real product id comes back (else net-new → retried).
+ if (!pid) return { ok:false, err: (topErr || r.raw || 'no-pid (empty response)').slice(0,160) };
psql(`UPDATE ${table} SET shopify_product_id='${String(pid).replace(/.*\//,'')}' WHERE dw_sku='${row.dw_sku.replace(/'/g,"''")}';`);
return { ok:true, pid };
}
@@ -256,7 +259,9 @@ async function createProduct(table, row, payload) {
const res = await createProduct(r.cfg.table, row, payload);
if (res.ok) { created++; if(created%10===0) process.stdout.write(`\r created ${created}…`); }
else { failed++; console.log(` ✗ ${row.dw_sku} ${JSON.stringify(res.err).slice(0,140)}`); }
+ if (res.stop) { console.log(`\n⛔ DAILY_VARIANT_LIMIT reached — stopping (resets in ~24h). created ${created} this run.`); break; }
}
+ if (failed && /* bail across vendors too once the daily cap is hit */ false) break;
}
// advance rotation
saveCursor({ idx: (start + picked.length) % ready.length, lastSlot: SLOT, lastRun: TODAY });
diff --git a/shopify/scripts/cadence/schu-reimport.sh b/shopify/scripts/cadence/schu-reimport.sh
index ef9d0f72..6f1446b1 100755
--- a/shopify/scripts/cadence/schu-reimport.sh
+++ b/shopify/scripts/cadence/schu-reimport.sh
@@ -38,7 +38,12 @@ zero=0
for i in $(seq 1 500); do
before=$(netnew)
[ "${before:-0}" -lt 5 ] && { echo "$(date '+%F %T') cleared mid-tick ($before)" >> "$LOG"; break; }
- node cadence-import.js --only Schumacher --skus 200 --commit >> "$LOG" 2>&1
+ out=$(node cadence-import.js --only Schumacher --skus 200 --commit 2>&1)
+ printf '%s\n' "$out" >> "$LOG"
+ if printf '%s' "$out" | grep -q "DAILY_VARIANT_LIMIT"; then
+ echo "$(date '+%F %T') Shopify daily variant-creation cap hit — exiting tick; resumes when the 24h window rolls" >> "$LOG"
+ break
+ fi
after=$(netnew)
if [ "${after:-0}" -ge "${before:-0}" ]; then zero=$((zero+1)); else zero=0; fi
echo "$(date '+%F %T') batch $i: $before -> $after (no-progress streak=$zero)" >> "$LOG"
← b6ac1130 schu-reimport: launchd-managed, restartable, loop-until-clea
·
back to Designer Wallcoverings
·
schu-reimport: macOS notification + CNCP win on completion ( 1020f066 →