# Troubleshooting symptom index

> A symptom index for Prophet 21, Epicor Kinetic and distribution metrics. Find what you are seeing, the usual cause and the guide section that explains the fix.

Source: https://docs.lumina-erp.com/reference/troubleshooting/

**In short.** Find the symptom, read the likely cause and follow the link to the guide section that explains it. Every row points back to a page on this site.

Each row names a symptom, the cause we see most often and the guide section that explains it. The causes are the usual ones, not the only ones, so confirm in your own system before you change anything.

:::tip[Place the problem first]
If your symptom is not listed, start with [using the map to place a problem](/prophet-21/how-p21-fits-together/#using-the-map-to-place-a-problem). Deciding which layer is at fault rules out most of the others.
:::

## Data and reports

| Symptom | Likely cause | Where to look |
|---|---|---|
| The same wrong value appears on screen, on a report and through the API | The data itself is wrong; look at what wrote it | [Using the map to place a problem](/prophet-21/how-p21-fits-together/#using-the-map-to-place-a-problem) |
| A query or report counts records that should not be there | Logically deleted rows were not filtered out | [Habits that keep queries safe](/prophet-21/reading-p21-data-with-sql/#habits-that-keep-queries-safe) |
| Rows repeat or mix across companies in a multi-company database | The join is on the record key without the company key | [Habits that keep queries safe](/prophet-21/reading-p21-data-with-sql/#habits-that-keep-queries-safe) |
| A report on the live system skips rows or counts some twice | `NOLOCK` or read uncommitted while data is moving | [Understand what your queries do to locking](/prophet-21/reading-p21-data-with-sql/#understand-what-your-queries-do-to-locking) |
| Extended values from a query are wrong by a large factor | Quantity in one unit of measure, price in another | [Lines on an order with what is still open](/prophet-21/reading-p21-data-with-sql/#lines-on-an-order-with-what-is-still-open) |
| An "available" figure from SQL disagrees with the screen | On hand minus allocated is not the P21 availability calculation | [Stock for an item across locations](/prophet-21/reading-p21-data-with-sql/#stock-for-an-item-across-locations) |
| Query results disagree with the numbers finance uses | The query was never reconciled to the report finance trusts | [When SQL is the wrong tool](/prophet-21/reading-p21-data-with-sql/#when-sql-is-the-wrong-tool) |
| A rebuilt report disagrees with the old one it replaced | The old report computed something different, including its known bugs | [Where BAQs go next](/epicor-kinetic/baq-fundamentals/#where-baqs-go-next) |
| Test orders reach real customers | Nobody can tell the play system from production at a glance | [Environments: production and a play copy](/prophet-21/how-p21-fits-together/#production-and-a-play-copy) |
| A value that must be protected was changed despite a hidden field | Hiding a field in Designer is not security | [DynaChange Designer: when the screen is the problem](/prophet-21/choosing-dynachange-or-integration/#dynachange-designer-when-the-screen-is-the-problem) |

## Printing and forms

| Symptom | Likely cause | Where to look |
|---|---|---|
| The transaction is right on screen and wrong on paper | The form: a formula, a format setting, a suppression condition or a field in the wrong section | [How transactional forms work](/prophet-21/custom-crystal-forms/#how-transactional-forms-work) |
| Customers suddenly receive plain, uncustomized invoices | The standard design was edited in place and an upgrade or repair overwrote it | [Change a custom copy, never the original](/prophet-21/custom-crystal-forms/#change-a-custom-copy-never-the-original) |
| A custom form broke after an upgrade | Fields the form uses were added, renamed or retyped | [Keep changes upgrade-safe](/prophet-21/custom-crystal-forms/#keep-changes-upgrade-safe) |
| Totals on a form are wrong though the data is right | A number converted to text and back, or formulas nested several levels deep | [Keep formulas simple and named clearly](/prophet-21/custom-crystal-forms/#keep-formulas-simple-and-named-clearly) |
| Large print batches are slow | Subreports or extra queries that run once per document | [Prefer supplied data over extra queries](/prophet-21/custom-crystal-forms/#prefer-supplied-data-over-extra-queries) |
| A line that should have printed is missing | A section suppressed when a value is zero | [Common pitfalls with custom forms](/prophet-21/custom-crystal-forms/#common-pitfalls-with-custom-forms) |
| Layout shifts or fonts change where the form actually runs | Fonts not installed on the server | [Common pitfalls with custom forms](/prophet-21/custom-crystal-forms/#common-pitfalls-with-custom-forms) |
| An old phone number, address or tax rate prints | The value is hard-coded in the form | [Common pitfalls with custom forms](/prophet-21/custom-crystal-forms/#common-pitfalls-with-custom-forms) |
| A form looks right printed and wrong by email | Fonts, margins and page size behave differently per output | [Test a form change with documents chosen to break it](/prophet-21/custom-crystal-forms/#test-a-form-change-with-documents-chosen-to-break-it) |

## Imports and integrations

| Symptom | Likely cause | Where to look |
|---|---|---|
| Screens work but overnight imports or jobs did nothing | A background service stopped, lost access to a file share or runs under an account whose password changed | [The application tier: middleware and background services](/prophet-21/how-p21-fits-together/#the-application-tier-of-middleware-and-background-services) |
| An import rejects rows or fills defaults you did not intend | A child record was loaded before its parent | [Load in dependency order](/prophet-21/planning-a-data-import/#load-in-dependency-order) |
| Creating customers or suppliers on a new install fails with unhelpful errors | The accounting foundation is not set up yet | [Load in dependency order](/prophet-21/planning-a-data-import/#load-in-dependency-order) |
| A load changed existing records instead of creating new ones | The load path matched existing records on a business key | [Choose the load method per object](/prophet-21/planning-a-data-import/#choose-the-load-method-per-object) |
| A rehearsal load looks cleaner than it should | It was loaded on top of a previous attempt instead of a reset baseline | [Rehearse until it is boring](/prophet-21/planning-a-data-import/#rehearse-until-it-is-boring) |
| Data problems fixed in play come back on cutover day | Hand fixes in the target vanish on the next refresh | [Fix bad data in the source or the mapping](/prophet-21/planning-a-data-import/#fix-bad-data-in-the-source-or-the-mapping) |
| The load finished but the numbers do not match | A successful load status is not proof of correctness | [Reconcile before you call it done](/prophet-21/planning-a-data-import/#reconcile-before-you-call-it-done) |
| Related tables are inconsistent after a data change | Someone wrote directly to the tables instead of using imports or APIs | [Direct database reads](/prophet-21/integration-options/#direct-database-reads) |
| An integration created the same order twice | No stable external reference checked before creating | [What happens when it fails?](/prophet-21/integration-options/#what-happens-when-it-fails) |
| Malformed data is rejected deep inside a batch | No validation at the edge before the write | [What happens when it fails?](/prophet-21/integration-options/#what-happens-when-it-fails) |
| Good data keeps getting overwritten with stale data | No agreed owner for each shared field | [Who owns which fields?](/prophet-21/integration-options/#who-owns-which-fields) |
| An integration stopped working after an upgrade | API or import layouts changed between versions | [What changes at upgrade time?](/prophet-21/integration-options/#what-changes-at-upgrade-time) |
| Order entry slows or stops whenever another system is slow or down | A business rule calls an external web service on save | [An integration: when another system is involved](/prophet-21/choosing-dynachange-or-integration/#an-integration-when-another-system-is-involved) |
| A hosted integration plan falls apart at build time | It assumed direct SQL access that the hosting agreement does not give | [On-premises versus hosted](/prophet-21/how-p21-fits-together/#on-premises-versus-hosted) |

## Performance

| Symptom | Likely cause | Where to look |
|---|---|---|
| Order entry hangs while a report or query runs | A long query holding shared locks, blocking writers | [Understand what your queries do to locking](/prophet-21/reading-p21-data-with-sql/#understand-what-your-queries-do-to-locking) |
| Locks stay held after a query finished | An uncommitted `BEGIN TRAN` left open in the query tool | [Habits that keep queries safe](/prophet-21/reading-p21-data-with-sql/#habits-that-keep-queries-safe) |
| "P21 is slow" everywhere at once | SQL Server health: index maintenance, statistics, backups, blocking; or the middleware tier | [The database: SQL Server holds the system of record](/prophet-21/how-p21-fits-together/#sql-server-holds-the-system-of-record) |
| Web client screens feel sluggish | Middleware capacity and health | [The clients: web and desktop](/prophet-21/how-p21-fits-together/#web-and-desktop-clients) |
| Scheduled jobs slow down people entering orders | Background work shares servers with users | [The application tier: middleware and background services](/prophet-21/how-p21-fits-together/#the-application-tier-of-middleware-and-background-services) |
| The whole Kinetic system slows after a new BPM | A directive on a busy method runs heavy logic on every call | [BPM cautions](/epicor-kinetic/functions-bpms-customizations/#bpm-cautions) |
| Every save of one table got slower | An in-transaction data directive doing too much | [Data directives](/epicor-kinetic/functions-bpms-customizations/#data-directives) |
| A BAQ is slow in grids or over REST | Too many columns, late filtering or criteria on a calculated field | [Performance habits that keep BAQs fast](/epicor-kinetic/baq-fundamentals/#performance-habits-that-keep-baqs-fast) |
| A large REST extract gets slower page by page | Deep `$skip` values | [Paging through large result sets](/epicor-kinetic/rest-v2-api/#paging-through-large-result-sets) |

## Kinetic BAQ and REST

### BAQ results

| Symptom | Likely cause | Where to look |
|---|---|---|
| A total is too large by roughly the average lines per order | A header value summed after joining to lines | [Mistake 1](/epicor-kinetic/baq-fundamentals/#summing-a-parent-value-after-a-join) |
| "One row per customer" turned into one row per customer per part | A non-aggregated child field joined the grouping | [Mistake 2](/epicor-kinetic/baq-fundamentals/#aggregating-in-the-wrong-subquery) |
| An open quantity is right on most rows and wrong on a few | Derived from a field other than requirement minus fulfilled | [Mistake 3](/epicor-kinetic/baq-fundamentals/#deriving-a-quantity-from-the-wrong-fields) |
| Rows drop out of a sum without an error | NULL from an outer join used in arithmetic | [Mistake 4](/epicor-kinetic/baq-fundamentals/#nulls-from-outer-joins) |
| An outer join does not return unmatched rows | A criterion on the outer-joined table | [Mistake 4](/epicor-kinetic/baq-fundamentals/#nulls-from-outer-joins) |
| A total adds amounts in different currencies | Document-currency fields summed across documents | [Mistake 5](/epicor-kinetic/baq-fundamentals/#mixing-currencies) |
| Decimals are truncated or large values cut off | Integer type or a short format on a calculated field | [Mistake 6](/epicor-kinetic/baq-fundamentals/#calculated-field-types-and-precision) |
| The order count is too high | Rows counted at line grain | [Mistake 7](/epicor-kinetic/baq-fundamentals/#counting-rows-instead-of-things) |

### REST calls

| Symptom | Likely cause | Where to look |
|---|---|---|
| 401 or 403 with a valid user | Missing or out-of-scope API key | [Authentication and API keys](/epicor-kinetic/rest-v2-api/#authentication-and-api-keys) |
| An order comes back with no lines | Child collections are not returned without `$expand` | [Why child collections come back empty](/epicor-kinetic/rest-v2-api/#empty-child-collections-and-expand) |
| Fewer rows than exist | Server row limits, or no paging | [Paging through large result sets](/epicor-kinetic/rest-v2-api/#paging-through-large-result-sets) |
| Records missing or repeated across pages | No `$orderby` on a unique key | [Paging through large result sets](/epicor-kinetic/rest-v2-api/#paging-through-large-result-sets) |
| Field not found | The name differs from what you expected; check `$metadata` | [Troubleshooting checklist](/epicor-kinetic/rest-v2-api/#troubleshooting-checklist) |
| Works in the browser API help, fails in code | Headers, especially `x-api-key`, or the company in the URL | [Troubleshooting checklist](/epicor-kinetic/rest-v2-api/#troubleshooting-checklist) |
| A retried write created a duplicate | No external reference checked before writing | [Writing data through business object methods](/epicor-kinetic/rest-v2-api/#writing-data-through-business-object-methods) |

### Customizations

| Symptom | Likely cause | Where to look |
|---|---|---|
| A rule holds on screen but imports and integrations bypass it | Validation lives only in an Application Studio layer | [Layer cautions](/epicor-kinetic/functions-bpms-customizations/#layer-cautions) |
| Nobody can explain why a save does something | A chain of BPMs triggering methods that trigger other BPMs | [BPM cautions](/epicor-kinetic/functions-bpms-customizations/#bpm-cautions) |
| Every caller of a Function broke at once | Its inputs or outputs changed | [Function cautions](/epicor-kinetic/functions-bpms-customizations/#function-cautions) |
| Old customizations do not run in the browser interface | They were built for the older Windows client | [Customizations from the older Windows client](/epicor-kinetic/functions-bpms-customizations/#customizations-from-the-older-windows-client) |

## Distribution numbers

### Inventory and replenishment

| Symptom | Likely cause | Where to look |
|---|---|---|
| Turns jump after a physical inventory or write-down with no change on the shelf | The averaging method or the write-down itself | [The averaging method changes the answer](/distribution/inventory-turns-and-gmroi/#the-averaging-method-changes-the-answer) |
| Turns look too good | Sales at selling price divided by inventory at cost | [Cost versus selling price](/distribution/inventory-turns-and-gmroi/#cost-versus-selling-price) |
| Turns look better than the warehouse performs | Drop-ship and special-order COGS counted in the numerator | [Consignment, drop-ship and non-stock items](/distribution/inventory-turns-and-gmroi/#consignment-drop-ship-and-non-stock-items) |
| Total turns look healthy while cash sits in old stock | A good average hiding a long dead tail | [Dead stock hiding behind a good average](/distribution/inventory-turns-and-gmroi/#dead-stock-hiding-behind-a-good-average) |
| Turns fell after opening a branch | Stock bought before the branch sells much | [New warehouses and growth](/distribution/inventory-turns-and-gmroi/#new-warehouses-and-growth) |
| The Census ratio suggests better turns than yours | The ratio uses sales at selling price, so it flatters turns by the markup | [The Census inventory-to-sales ratio](/distribution/inventory-turns-and-gmroi/#the-census-inventory-to-sales-ratio) |
| An item with a purchase order on the way triggers a second one | The reorder point is compared to shelf stock, not available plus on order | [Reorder point](/distribution/safety-stock-reorder-point-eoq/#reorder-point) |
| Growing items run out and declining ones pile up | Min and max have gone stale | [Min/max in the ERP](/distribution/safety-stock-reorder-point-eoq/#minmax-in-the-erp) |
| Turns fall and fill rate does not rise | Buffers are in the wrong places | [Setting your replenishment parameters](/distribution/safety-stock-reorder-point-eoq/#setting-your-replenishment-parameters) |

### Service levels

| Symptom | Likely cause | Where to look |
|---|---|---|
| Line, unit and order fill differ by 10 points or more in one month | They are different measures, and that spread is normal | [Worked example (fill rate)](/distribution/fill-rate-and-otif/#worked-example) |
| A customer OTIF scorecard disagrees with yours | A different date, window or unit of measure in their definition | [Why OTIF definitions differ](/distribution/fill-rate-and-otif/#why-otif-definitions-differ-between-trading-partners) |
| Backorder rate rises while fill rate holds steady | Customer service has stopped offering alternatives | [Backorder rate](/distribution/fill-rate-and-otif/#backorder-rate) |
| Fill rate moves with no change in stock | Substitutions, partials, drop-ship, future-dated or cancelled lines or unit changes | [What distorts the numbers](/distribution/fill-rate-and-otif/#what-distorts-the-numbers) |
| Overstock after setting safety stock to a customer fill-rate target | A fill-rate target entered as a cycle service level | [Fill rate versus cycle service level](/distribution/fill-rate-and-otif/#fill-rate-versus-cycle-service-level) |

### Cost, price and cash

| Symptom | Likely cause | Where to look |
|---|---|---|
| Heavy, bulky or imported items look more profitable than they are | Inbound freight booked to overhead instead of item cost | [Why landed cost changes margin reporting](/distribution/landed-cost-and-freight-terms/#why-landed-cost-changes-margin-reporting) |
| Margins overstated on items sold before the freight bill arrived | Re-costing only when the bill arrives | [When costs arrive after receipt](/distribution/landed-cost-and-freight-terms/#when-costs-arrive-after-receipt) |
| The average cost of the last few units jumps | A late charge added under average costing after most units shipped | [When costs arrive after receipt](/distribution/landed-cost-and-freight-terms/#when-costs-arrive-after-receipt) |
| Item margins shift between periods with no change in the business | The freight allocation method changed | [Choosing a method](/distribution/landed-cost-and-freight-terms/#choosing-a-method) |
| Margin erodes though nobody changed a price | Supplier cost increases that never reached price, overrides or stale contracts | [Where pricing leaks margin](/distribution/pricing-and-margin/#where-pricing-leaks-margin) |
| The cash conversion cycle looks shorter than it is | Inventory or payables divided by revenue instead of COGS | [Using revenue for DIO or DPO](/distribution/cash-conversion-cycle/#using-revenue-for-dio-or-dpo) |
| The cycle looks best at year end | Year-end balances instead of an average of month-ends | [Using year-end balances only](/distribution/cash-conversion-cycle/#using-year-end-balances-only) |
| DSO, DIO and DPO do not add up to a real cycle | Each was measured over a different period | [Mixing periods](/distribution/cash-conversion-cycle/#mixing-periods) |
| The inventory subledger does not tie to the GL | Manual entries, cutoff timing, in-transit transfers, unit errors or posting setup | [Common reasons inventory does not tie to the GL](/erp-projects/month-end-close-for-distributors/#common-reasons-inventory-does-not-tie-to-the-gl) |

### Units of measure and counting

| Symptom | Likely cause | Where to look |
|---|---|---|
| A line is priced 100 times too high or 1,000 times too low | A per-hundred or per-thousand price keyed against the wrong unit | [Price per hundred and per thousand](/distribution/units-of-measure/#price-per-hundred-and-per-thousand) |
| Extended costs drift on cheap parts | Unit cost stored with too few decimals | [Rounding the factor or the cost](/distribution/units-of-measure/#rounding-the-factor-or-the-cost) |
| Receipts and invoices do not match the PO, and three-way matching fails | The supplier unit or pack size differs from yours | [Supplier units that differ from yours](/distribution/units-of-measure/#supplier-units-that-differ-from-yours) |
| Scanning a case receives one each | The case GTIN is stored against the each | [GS1 identifiers](/distribution/units-of-measure/#gs1-identifiers) |
| Quantities on open documents changed after a unit edit | A conversion factor changed on a live item | [Changing a factor on a live item](/distribution/units-of-measure/#changing-a-factor-on-a-live-item) |
| Net dollar variance is zero but records are wrong | Offsetting errors; manage on the hit rate, not the net | [Measure inventory record accuracy](/distribution/abc-analysis-and-cycle-counting/#measure-inventory-record-accuracy) |
| Counts keep matching the system even when stock is off | Counters can see the expected quantity | [Run the cycle count program](/distribution/abc-analysis-and-cycle-counting/#run-the-cycle-count-program) |
| Record accuracy stays flat despite more counting | Root causes are adjusted away, not fixed | [Check that it worked](/distribution/abc-analysis-and-cycle-counting/#check-that-it-worked) |

---

Epicor, Prophet 21, P21 and DynaChange are trademarks or registered trademarks of Epicor Software Corporation registered in the United States and other countries. Kinetic is a trademark of Epicor Software Corporation. Lumina ERP is an independent consultancy and is not affiliated with, sponsored by or endorsed by Epicor.
