Vista Watch: early access

Altura Innovation Technology Partners

Integration error library · NetSuite + Celigo + Shopify

The integration errors that actually break a NetSuite stack, and how to fix them.

A working reference for the failure modes we see most when NetSuite, Celigo, and Shopify run together: what the error means, how to fix it, and how to keep it from coming back. Most of these break silently: the order drops, the tax double-reports, the script never fires, so the cost shows up at reconciliation, not in an alert.

From real rescues, anonymized · Celigo Advanced Partner

The library

Patterns indexed

28

Failure groups

5

Systems in scope

4

Every entry carries

Symptom · root cause · fix · how to prevent it recurring.

How to use this

Find the symptom, read the cause, apply the fix.

  • Each entry is the literal error or symptom, what is actually causing it, the fix, and how to keep it from coming back.
  • Every pattern is distilled from real NetSuite + Celigo + Shopify rescues, generalized to the product, with no client names or confidential detail.
  • Most of these fail silently: the order drops, the tax double-reports, the script never fires. The signal is in reconciliation, not an alert.
  • When the fix is bigger than a config change, that is the moment to bring in help before a parallel run or a close.

NetSuite · OAuth 1.0

401 Unauthorized from a NetSuite RESTlet

Celigo · SuiteScript hook

entry point("yourFunction") is not a function

NetSuite · SuiteScript governance

SSS_USAGE_LIMIT_EXCEEDED partway through a scheduled or Map/Reduce run

Celigo · Shopify rate limits

429 Too Many Requests / throttled from Shopify during a burst

Shopify → NetSuite · Celigo

Duplicate Sales Orders during a parallel / cutover run

Shopify → NetSuite · Celigo

Dropped orders · value_lookup_failed on item match

NetSuite · SuiteScript / Workflow

NetSuite scripts silently do not fire on Celigo-created records

Celigo · flow filter

A tag or attribute filter matches more records than intended

Shopify → NetSuite · multiple middleware

One storefront order writes to NetSuite twice from two systems

Shopify → NetSuite · date handling

Orders land on the wrong day or in the wrong period vs the storefront

NetSuite · order dedup

A "duplicate order" alarm that is really related records sharing one order number

Shopify → NetSuite · tax

Avalara double-reports tax on Shop Pay / marketplace orders

Shopify → NetSuite · Celigo

Every payment lands in Undeposited Funds; bank rec will not tie by gateway

Shopify → NetSuite · Celigo

NetSuite gross sales ≠ Shopify gross; discounts are invisible

Shopify → NetSuite · line pricing

Multi-quantity lines are understated; totals only miss when qty > 1

OMS/Celigo → NetSuite · multi-currency

Foreign-currency sales post in the home currency and reprice to the domestic list price

Shopify → NetSuite · price levels

The NetSuite invoice does not match what the storefront charged

Shopify → NetSuite · refunds

Order refunded on the storefront but the NetSuite invoice is still open

NetSuite · multi-currency deposits

Deposit posts in settled currency while the invoice posts in presentment currency. They never tie

Shopify → NetSuite · gift cards

Gift cards break the payout: booked as revenue when sold, or missed when redeemed

NetSuite → Shopify · fulfillment

Fulfillments fail silently / post with incomplete line items (Shopify Plus)

Shopify → NetSuite · Celigo

Duplicate Sales Orders from repeated Shopify webhooks

NetSuite → Shopify · inventory

Oversell when many Shopify variants map to one NetSuite item

NetSuite → Shopify · inventory / locations

Storefront oversells because a location's availability never syncs

Shopify → NetSuite · kits & bundles

A bundle/kit SKU oversells or mis-costs because components are not tracked

Celigo · delta / scheduled flows

Records skipped during an outage never come back after the fix

Celigo · error-queue cleanup

Bulk-resolving an error queue silently drops a real record hiding in it

Shopify → NetSuite · customer match

A migration creates duplicate customers; later orders fail on multiple matches

01 · Connectivity & deployment

The integration cannot authenticate, or a deploy quietly broke something that was working yesterday.

NetSuite · OAuth 1.0

401 Unauthorized from a NetSuite RESTlet

What is happening
The OAuth 1.0 signature base string must include the URL's query parameters (the ?script= and &deploy= on the RESTlet URL). If the signing routine builds the base string from the bare URL and drops the query params, the signature it produces does not match what NetSuite recomputes, so NetSuite rejects it as 401. Calls with no query string sign correctly and succeed, which is why the failure looks intermittent.
How to fix it
Parse the full RESTlet URL, extract its query parameters, and merge them with the OAuth parameters before computing the signature base string. The script and deploy IDs have to be part of what you sign, not just part of where you send it.
Prevent it
Route every OAuth-signed call through one signing function instead of hand-rolling per call, and add a test fixture whose URL carries query parameters so a regression in the base-string logic fails the test, not production.

Celigo · SuiteScript hook

entry point("yourFunction") is not a function

What is happening
Celigo shared scripts are monolithic: one script file holds the hook functions for several flows (e.g. the EDI 850 / 855 / 856 map hooks). The Celigo script editor saves whatever is in the editor window as the complete script. If you paste only the function you edited and save, Celigo replaces the entire script with that one function and silently wipes the rest. Every flow whose entry point is now missing fails on its next run with entry point("…") is not a function.
How to fix it
Rebuild the complete script with every function present and save it once as a unit, not just the function you changed. Then re-run one record per flow that shares the script to confirm all entry points resolve.
Prevent it
Never save a partial Celigo script. Before editing, copy the full current script out of Celigo and commit it as a dated backup; make your change in that full copy; paste the whole file back; save; then smoke-test one transaction per flow before you close the tab.

NetSuite · SuiteScript governance

SSS_USAGE_LIMIT_EXCEEDED partway through a scheduled or Map/Reduce run

What is happening
Most SuiteScript record operations spend units from a fixed per-execution governance budget (loads and saves cost the most; some calls are cheap or free). A loop that does a record.load and record.save on every row burns units fast: a small batch finishes under budget, but a large one runs out mid-run and NetSuite aborts the script. It looks intermittent, and it leaves the batch half-processed: the rows before the limit posted, the rest did not.
How to fix it
Convert the job to a Map/Reduce script so each key gets its own governance budget, and replace per-record record.load calls with search.lookupFields / record.submitFields where you only need a few fields. For anything that must stay a scheduled script, yield and reschedule before the remaining units run out.
Prevent it
Budget governance during design, not after a failure: estimate units per record times worst-case volume, and load-test at realistic batch size. A job that half-completes silently is worse than one that errors cleanly. You have to find where it stopped.

Celigo · Shopify rate limits

429 Too Many Requests / throttled from Shopify during a burst

What is happening
Shopify's API is rate-limited: a leaky-bucket on REST, a cost-based budget on GraphQL. A flow that fires requests as fast as it can (common on a flash-sale spike, or a historical backfill run at full speed) drains the budget and Shopify returns 429. If the flow does not honor Shopify's throttle signal, records error out instead of slowing down.
How to fix it
Cap the flow's concurrency and add exponential backoff that respects Shopify's throttle headers (Retry-After on REST, the throttleStatus on GraphQL). Run a large backfill off-peak at reduced concurrency rather than at full speed against live order traffic.
Prevent it
Size the connector's concurrency to Shopify's published limits, and treat any backfill as a scheduled, throttled job, not a run-it-all-now operation that competes with real-time order sync for the same API budget.

02 · Order & item sync

Orders duplicate, drop, or skip the automation that was supposed to run on them.

Shopify → NetSuite · Celigo

Duplicate Sales Orders during a parallel / cutover run

What is happening
The old and new middleware write the same Shopify order to NetSuite using different externalId formats, for example a prefixed format like SHPF-{location}-{order-id} from a legacy build versus the plain numeric Shopify order id from the new one. NetSuite dedups on externalId, so two different formats for the same order read as two different records and you get two Sales Orders.
How to fix it
Standardize on one externalId format (usually the plain Shopify order id) across every flow before any parallel run, so the new flow matches and updates the existing record instead of creating a second one.
Prevent it
Before turning on a parallel run, query NetSuite for recent orders whose externalId still uses the legacy format: the count from the new flows should be zero. Treat externalId format alignment as a hard go/no-go gate, not a detail.

Shopify → NetSuite · Celigo

Dropped orders · value_lookup_failed on item match

What is happening
The flow links a Shopify line to a NetSuite item by a match key (commonly NetSuite name/SKU to Shopify sku, or NetSuite upccode to Shopify barcode). If that key is blank on the NetSuite item, the lookup returns nothing and the order drops. If the key is not unique on the NetSuite side, the lookup is non-deterministic: Celigo resolves to an arbitrary item or fails outright.
How to fix it
Audit the match key on every active item that sells online: it must be populated and unique. Run a duplicate-value saved search on the key before changing any flow, and fill the gaps in the item master before the next sync.
Prevent it
Treat the match key as data, not config: a blank key is a dropped order and a duplicate key is a non-deterministic write. Validate population and uniqueness whenever you add items or change the match field, and keep merch data discipline (barcode/UPC always populated on new listings).

NetSuite · SuiteScript / Workflow

NetSuite scripts silently do not fire on Celigo-created records

What is happening
User Event scripts and workflow actions that filter on executionContext run only in the contexts they list. Records created through a CSV import or the UI arrive in one context; records Celigo creates arrive as WEB_SERVICES. A script gated to CSV_IMPORT (or to the UI) never fires for Celigo-created records, no error, the automation just does not happen, so validations and auto-populates are silently skipped.
How to fix it
Audit every User Event script and workflow for an execution-context filter. For each one that should run on integration-created records, add WEB_SERVICES to its allowed contexts, or remove the context filter if the logic is always applicable.
Prevent it
Make a context-filter audit a standard step whenever you move record creation from CSV import or the UI onto an iPaaS. It is the highest-risk silent failure in that kind of migration precisely because nothing errors.

Celigo · flow filter

A tag or attribute filter matches more records than intended

What is happening
A contains filter on a tag or attribute matches any value that contains the substring, not the whole token. A filter meant to catch "sale" also catches "wholesale" and "sale_migration". Switching to equals breaks the other way, because platforms often send tags as one comma-joined string ("sale, clearance") that never equals the single token. Either way the wrong population flows, and it is easy to miss until the counts are off.
How to fix it
Match on a whole token, not a substring: split the comma-joined tag string and compare each token exactly, or, more reliably, filter on a single unique marker value you control rather than a common word. (A compound like contains "sale" AND NOT contains "sale_migration" still matches "wholesale", so it is a patch, not a fix.) Confirm where the filter runs, too: a filter on the import step still pulls every record each run and only drops them after fetch, so filter at the export/source step when the connector allows it.
Prevent it
Never filter a production population on a broad substring. Reserve one unambiguous marker tag or field for integration routing, and test the filter against real multi-tag strings before enabling it, including values that contain your target word as a substring.

Shopify → NetSuite · multiple middleware

One storefront order writes to NetSuite twice from two systems

What is happening
Two systems read the same storefront, for example a Celigo order flow and a separate order-management (OMS) middleware, and both write to NetSuite. It stays hidden while each handles a different order source. But a migration, or an unmapped order source (a bulk-import app's source_name, say) that neither system was scoped to exclude, falls through to both and the order lands twice.
How to fix it
Map every reader of the storefront and define exactly one owner per order source. Add the stray source to the OMS's channel map so it is not defaulted to "web" and synced, or exclude it from the Celigo filter, whichever system should not own it. Reconcile both paths when cleaning up, not just the one you noticed.
Prevent it
Treat "which system writes this record to NetSuite" as a single-owner decision per source, written down. Before any migration or new order source, confirm it is claimed by exactly one integration: an unclaimed source defaults somewhere you did not choose.

Shopify → NetSuite · date handling

Orders land on the wrong day or in the wrong period vs the storefront

What is happening
Shopify timestamps orders in UTC; NetSuite posts by the account's time zone. An order placed at 9pm Pacific is already "tomorrow" in UTC, so if the integration passes the raw UTC date through, that order books a day late, and at month-end it lands in the wrong accounting period. Daily and period totals drift by exactly the orders sitting near the boundary.
How to fix it
Convert the storefront timestamp to the NetSuite account time zone before setting the transaction date, so the posted date matches the local business day. Confirm the connector's date mapping performs that conversion rather than truncating the raw UTC timestamp.
Prevent it
Reconcile a day's order count storefront-to-NetSuite at least once after go-live and always around a period close, so a time-zone offset surfaces as a boundary discrepancy instead of a silent period-cutoff error.

03 · Money & reconciliation

The deposits and the books do not tie out, usually because tax, gateways, or discounts are modeled wrong at the source.

Shopify → NetSuite · tax

Avalara double-reports tax on Shop Pay / marketplace orders

What is happening
Shop Pay (and other marketplace-facilitator payment methods) sets tax_lines[].channel_liable = true on the Shopify order, meaning the facilitator, not the merchant, is liable to remit that tax. If the integration does not carry that flag into NetSuite, the merchant's tax engine remits tax the facilitator already owes, double-reporting it.
How to fix it
Read tax_lines[].channel_liable on every order, set a NetSuite custom body flag on the Sales Order when it is true, and configure the Avalara/NetSuite connector to suppress remittance when that flag is set. Create the custom field if it does not exist yet.
Prevent it
Map facilitator-liable tax explicitly for every channel that can produce it (Shop Pay, marketplace pay methods), and reconcile remitted tax against facilitator-liable orders during close so a missed flag surfaces immediately.

Shopify → NetSuite · Celigo

Every payment lands in Undeposited Funds; bank rec will not tie by gateway

What is happening
On the NetSuite Customer Deposit, undepfunds defaults to TRUE, and while it is TRUE NetSuite ignores the account field and routes everything to Undeposited Funds regardless of what you mapped. Modern bank reconciliation needs each payment gateway in its own clearing account, which never happens while that flag is on.
How to fix it
Set undepfunds = FALSE on the Customer Deposit, then map each Shopify payment_gateway value (shopify_payments, shop_pay, paypal, gift_card, …) to its own NetSuite clearing-account internal id. Get the actual account ids from finance; do not assume them.
Prevent it
Make the gateway-to-clearing-account map an explicit, finance-owned table in the integration design, and reconcile each gateway's clearing account to its processor payout so a misroute shows up as a non-zero balance.

Shopify → NetSuite · Celigo

NetSuite gross sales ≠ Shopify gross; discounts are invisible

What is happening
The integration is syncing Shopify discounts as item price adjustments instead of discount line items. A price adjustment hides the discount inside the item's revenue, so gross sales are understated, the discount never hits a promo GL account, SKU-level margins bounce per order, refunds on discounted orders become ambiguous, and the tax base can be wrong.
How to fix it
Switch the integration to discount line items: create a non-inventory discount item in NetSuite mapped to a discount/promo GL account, and let Shopify's per-line discount_allocations map to a discount line rather than reducing the item price.
Prevent it
Treat this as a reporting and reconciliation requirement, not a technical preference: the CFO will eventually ask what was discounted last month, and only discrete discount lines can answer it. Configure it correctly at build; untangling it historically is expensive.

Shopify → NetSuite · line pricing

Multi-quantity lines are understated; totals only miss when qty > 1

What is happening
The mapping writes the storefront unit price into the NetSuite line Amount field instead of Rate. When Amount is passed directly, NetSuite keeps it as the line total instead of computing Rate times Quantity, so a line for 3 units at $40 posts as $40, not $120. At quantity 1 the two are identical (Amount equals Rate times 1), so it is invisible on single-item orders and reads as intermittent "variance" that can persist for years.
How to fix it
Map the unit price to the line Rate field and let NetSuite compute Amount = Rate times Quantity. Then correct history: any open line where Amount does not equal Rate times Quantity and Quantity is greater than 1 is affected. Tax calculates off the corrected base, so re-check tax on the fixed orders.
Prevent it
On every order flow, verify the unit price maps to Rate, not Amount, and add a standing detector: a saved search or SuiteQL for lines where Amount does not equal Rate times Quantity and Quantity is greater than 1. Treat its output as candidates, not proof: discounts, custom price levels, unit-of-measure conversions, tax-inclusive pricing, and rounding can legitimately break that equality, so review before correcting. Even so, it is the highest-value single thing to confirm on a new order integration.

OMS/Celigo → NetSuite · multi-currency

Foreign-currency sales post in the home currency and reprice to the domestic list price

What is happening
The order feed does not carry the transaction currency, so the sales order posts in the customer record's default (domestic) currency. When it posts domestic, NetSuite typically resolves the item's domestic price level and reprices the line to the home-currency list price, ignoring the foreign amount charged (unless the flow explicitly passes a rate or amount). The foreign order then carries a gap between what was charged, what settled, and what NetSuite booked.
How to fix it
Assign the correct transaction currency on the imported order (via the feed mapping or the customer record) so NetSuite resolves the matching foreign price level. If the upstream feed strips currency entirely, the durable fix is to read presentment currency from the storefront object directly, a connector that carries it end-to-end, rather than patching downstream.
Prevent it
For any cross-border storefront, confirm the order feed carries a currency field before go-live. A feed that omits currency pushes the transaction toward domestic repricing, and a downstream rate field alone rarely fixes it while the transaction itself still posts in the wrong currency.

Shopify → NetSuite · price levels

The NetSuite invoice does not match what the storefront charged

What is happening
When the integration prices lines from a NetSuite price level (the item's list price) rather than the exact amount charged, any time the storefront price differs (a flash sale, a discount code, a stale price that was never synced) NetSuite books the list price and the invoice stops tying to the deposit. It is loudest on foreign orders, where imperfect currency handling makes the gap show on nearly every order, but it happens on any domestic order sold at a non-list price.
How to fix it
Carry the actual charged unit price from the storefront onto the line rather than relying on the NetSuite price level, or keep the price levels genuinely in sync with the storefront. Reconcile invoice-to-deposit by order and true-up the residual to a named variance account under a defined policy.
Prevent it
Decide deliberately whether NetSuite prices from its own levels or honors the storefront amount, and make sure discounts flow as discrete lines. If you price from levels, add an invoice-vs-charged variance report so the gap is measured, not discovered at audit.

Shopify → NetSuite · refunds

Order refunded on the storefront but the NetSuite invoice is still open

What is happening
The refund happened on the storefront or at the processor, but the refund event never synced to NetSuite, or synced as an unlinked credit. The original invoice stays open and billed, so AR overstates receivables, the deposit for that order never ties, and the customer looks like they owe money that was already returned to them.
How to fix it
Sync the refund event and apply it against the original transaction (a return authorization and credit memo, or a refund that references the original order) so the invoice closes. Find the existing leaks by reconciling storefront refunds against open NetSuite invoices for the same orders.
Prevent it
Include refunds and returns as a first-class flow, not an afterthought, and reconcile refunded storefront orders against NetSuite AR during close so a refund-sync gap surfaces as an open-invoice exception.

NetSuite · multi-currency deposits

Deposit posts in settled currency while the invoice posts in presentment currency. They never tie

What is happening
A cross-border sale has two currencies: the presentment currency the customer was charged and the settlement currency the processor pays out. If the deposit feed carries only the settled home-currency amount while the invoice is in presentment currency, the two are in different units and will not tie without modeling the exchange and processor payout explicitly. Worse, flipping the sale to presentment currency before the deposit source also carries it makes the gap larger, not smaller.
How to fix it
Get the deposit source to carry presentment currency (or read it from the storefront/processor object directly) before switching the sale to that currency. Sequence it: do not enable foreign-currency recognition on orders until the deposit leg is also in that currency, or the invoice and deposit diverge harder.
Prevent it
Map both presentment and settlement currency end-to-end before any multi-currency go-live, and treat "the deposit source carries presentment currency" as a hard prerequisite gate for turning on foreign-currency recognition.

Shopify → NetSuite · gift cards

Gift cards break the payout: booked as revenue when sold, or missed when redeemed

What is happening
A gift card is two different events that are easy to conflate. Selling one is a liability, not revenue; redeeming one is a tender (payment method), not a discount or a sale. If the integration books a gift-card sale as revenue, or treats a redemption as a price reduction instead of a tender against the liability, the payout no longer ties and the gift-card liability on the balance sheet drifts.
How to fix it
Map gift-card sales to a liability account and gift-card redemptions to a tender that draws that liability down, mirroring how the storefront reports them, so neither one lands in revenue. Reconcile the gift-card liability against outstanding card balances.
Prevent it
Model gift cards explicitly at build time as (1) a liability on sale and (2) a tender on redemption. It is a known reconciliation trap; retrofitting the accounts after months of mixed postings is expensive.

04 · Fulfillment & inventory

Fulfillments fail or oversell because an API was deprecated or an event fired more than once.

NetSuite → Shopify · fulfillment

Fulfillments fail silently / post with incomplete line items (Shopify Plus)

What is happening
Shopify's legacy fulfillment endpoints create fulfillments directly from order_id and are deprecated in favor of the Fulfillment Orders API, which requires a separate fulfillment_order_id resource. An integration still on the legacy path fails silently or writes incomplete line-item data. It bites first on multi-location and Shopify Plus orders, where fulfillment is split across several fulfillment orders.
How to fix it
When processing an order, also retrieve its fulfillment_orders (a separate API call) and use fulfillment_order_id and fulfillment_order_line_items to create the fulfillment. Confirm your Celigo Shopify connector version supports the Fulfillment Orders API; older templates use the legacy one.
Prevent it
Treat any flow Shopify or Celigo labels deprecated as a time bomb: migrate it during discovery rather than waiting for breakage, and verify connector/template versions against current product docs before go-live.

Shopify → NetSuite · Celigo

Duplicate Sales Orders from repeated Shopify webhooks

What is happening
Shopify webhook delivery is at-least-once, not exactly-once: the same event can fire again on a network retry, a Shopify replay, or a subscription re-registration. A listener that creates a NetSuite record on every delivery, without checking whether one already exists, produces duplicates. (Scheduled polling is naturally idempotent; webhook listeners are not.)
How to fix it
Before creating a Sales Order, look up NetSuite by externalId = Shopify order id and update the existing record instead of creating a new one when it is found. Use Celigo's built-in duplicate detection where it is available.
Prevent it
Design every create-on-event flow to be idempotent and test it deliberately: cancel and refire, force a timeout retry, and use Shopify's webhook replay tool to confirm a second delivery updates rather than duplicates.

NetSuite → Shopify · inventory

Oversell when many Shopify variants map to one NetSuite item

What is happening
Under a many-to-one match (N Shopify variants to one NetSuite item), every variant advertises the same available quantity. Between an order dropping the NetSuite quantity and the next inventory push updating all the variants, more than the true available stock can be committed across the variants. The async-sync window is inherent to any inventory sync, but many-to-one multiplexes demand across more SKUs, so the risk compounds.
How to fix it
Tighten the inventory push cadence for thin-stock items (sub-hourly), use a real-time inventory flow where volume justifies it, and expose a safety-buffered available quantity to Shopify (NetSuite stock minus a threshold) rather than the raw number.
Prevent it
Decide many-to-one deliberately as a data-model choice with a stated oversell mitigation, not as a quiet field-mapping change, and size the inventory-cadence work into the build instead of discovering it after a stockout.

NetSuite → Shopify · inventory / locations

Storefront oversells because a location's availability never syncs

What is happening
The inventory feed publishes availability from specific NetSuite locations to specific storefront locations. NetSuite still relieves on-hand from whatever location fulfills the order. That part works. The failure is the other direction: if a NetSuite location is not mapped into the availability feed (a new warehouse, a 3PL, a retail store), its stock levels never publish to the storefront, so Shopify keeps advertising a stale or default number and oversells. A newly added location is the usual trigger.
How to fix it
Add the missing location to the location map on the availability/inventory feed (and to the fulfillment flow so its fulfillments post back), then reconcile the storefront's advertised availability against NetSuite on-hand for that location. Confirm the map covers every location whose stock should be sellable online, including 3PLs.
Prevent it
Make "add it to the integration location map" a required step in the checklist for standing up any new fulfillment location, so a new warehouse cannot silently drop out of the availability feed.

Shopify → NetSuite · kits & bundles

A bundle/kit SKU oversells or mis-costs because components are not tracked

What is happening
The storefront sells a single bundle SKU, but in NetSuite the real inventory usually lives in the component items. If the integration maps the bundle to a standalone item, component stock never moves when a bundle sells, so components oversell, and margin is wrong because the standalone item carries no component cost. The right target depends on the item type: a Kit/Package relieves its member items on fulfillment, whereas an Assembly relieves the assembly item at sale and consumes components only at build, so its sellable number is the buildable quantity, not raw component stock.
How to fix it
Map the storefront bundle to the matching NetSuite structure: a Kit/Package item so members relieve on fulfillment, or explode the bundle into component lines on import. If the bundle is an Assembly, drive availability off buildable quantity and keep build orders current, since a sale does not itself relieve components. Reconcile component on-hand after the change.
Prevent it
Decide bundle handling as a data-model choice at build, Kit/Package vs Assembly vs exploded lines, with a stated inventory and costing treatment, and confirm the right stock actually moves when a bundle sells before you trust the availability number.

05 · Recovery & cleanup

The break is fixed, but the records it already damaged need a deliberate recovery: backfills, retries, and cleanups that can quietly make it worse.

Celigo · delta / scheduled flows

Records skipped during an outage never come back after the fix

What is happening
A scheduled or delta flow tracks a cursor (a last-modified timestamp or an id high-water mark) and only pulls records newer than the cursor. Records skipped while the flow was misconfigured or down are now behind the cursor, so fixing the flow going forward never re-picks them up. The fix stops new damage but does not repair the gap.
How to fix it
Recover the missed window explicitly: set the delta start back to before the outage for a controlled backfill, or run an on-demand / real-time companion flow (ideally one built to share the same mapping and scripts) for the affected records. Confirm the idempotence key first, so re-runs update existing records rather than duplicating them.
Prevent it
For any delta flow, know how to backfill before you need to, and keep an on-demand companion flow available. After any outage, define the exact missed window and reconcile record counts for it rather than assuming forward operation caught up.

Celigo · error-queue cleanup

Bulk-resolving an error queue silently drops a real record hiding in it

What is happening
When a filter fix turns a flood of bad records into should-be-ignored errors, mass-resolve clears the queue fastest, but it also silently discards any genuine record mixed into the queue for an unrelated reason. Retry re-runs each record through the corrected logic (the junk now fails the filter and self-clears), which is slower but self-validating. Resolve is fast and lossy. (A console that caps the visible error list is showing a display limit, not losing data.)
How to fix it
Mass-retry rather than resolve when a queue mixes junk with possibly-real records; retry proves each one against the fixed logic. Only resolve after you have confirmed the queue contains nothing you still need.
Prevent it
Before bulk-clearing any error queue, sample it for genuine records, and prefer retry (self-validating) over resolve (silent drop). Treat resolve as final. It does not process the record, so anything real in the queue is simply gone from the flow.

Shopify → NetSuite · customer match

A migration creates duplicate customers; later orders fail on multiple matches

What is happening
The order flow matches a storefront customer to a NetSuite customer by a key, often email or name. A migration that loads customers without deduping against existing records, or a match key that is not unique (email can be blank, shared, or reused), leaves two NetSuite customers for one person. The next order that matches on that key returns more than one record, so the flow errors on a multiple-match condition or attaches the order to the wrong customer.
How to fix it
Prefer a deterministic key, the storefront customer id mapped to the NetSuite external id, over email or name, which are weaker. Dedupe the customer master on that key, merge the duplicates the migration created, and re-run the failed orders after the merge.
Prevent it
Before any customer migration, dedupe the load against existing records on a deterministic source id, and validate that the match key is unique in NetSuite. A non-unique match key is a standing source of misattached orders, not a one-time migration artifact.

Why this is specific

These are not generic checklists. Every pattern came out of a real NetSuite, Celigo, or Shopify rescue, generalized to the product, with the client, the contract, and the confidential detail left out.

If your symptom is here, the fix is here. If it is bigger than a config change (a parallel run, a cutover, a close that will not tie) that is the right time to bring someone in.

Looking at an error this list didn't solve?

Send us the error message and what you were doing when it fired. We will tell you what it means and what it takes to fix, whether that is a config change or a rescue.