Why is COGS zero on a sale?
A fulfilled order shows $0.00 COGS and a margin that is far too high. Find out why the product had no cost when it shipped, and fix the sales after it.
The short answer
- A line's COGS is set once, when you fulfill the order: the quantity times the product variation's weighted-average cost as shown, to the cent, at that moment, or its recipe's cost when it has no stock and no cost from real stock. $0.00 means Trackost had no cost to use.
- The usual cause is a product with no completed batch, no cost basis and no recipe, or stock and recipes made from materials that had no cost yet.
- An open order warns you first: a line with no cost to use reads 'No cost yet' instead of an estimate. A line that isn't matched to a product has no COGS at all.
- Fixing the cause corrects the sales that come after it. Trackost never re-costs an order it has already fulfilled.
How COGS is set
When you click Fulfill & mark shipped, Trackost multiplies each line's quantity by the cost of its product variation at that moment, as shown, to the cent, and stores the result on the line. That is the line's COGS, and it never changes afterwards. The order's COGS card adds up its lines, True profit is revenue minus fees minus COGS, and Margin is true profit divided by the revenue of the lines that have a COGS. Only team members with money access see these cards.
The cost comes from what put the stock there:
- For a product you make, your completed batches: the materials each batch used, at their own weighted-average costs, plus labor.
- For a product you buy in, the Cost basis you give when you add its stock on Inventory.
- For a product with no stock whose cost never came from real stock, its recipe: the recipe's Unit cost (incl. labor) at that moment. Fulfilling then shows 'Costed from the recipe'.
With none of those, the sale records $0.00.
An Open order reads 'No cost yet'
Before you fulfill, an open order's cards show an estimate, marked Est., of what fulfilling would record at today's cost. A line whose product has no cost to use is left out of it, and the True profit card says how many lines have no cost yet. When that is every matched line, the cards read 'No cost yet', and so does the order's True profit on the Orders list.
Fulfilled as it is, such a line goes out at $0.00. Fix the cause first, as Fix the cause describes, and the sale is costed when you fulfill. Fulfill an order and see its true profit walks through fulfilling.
COGS reads $0.00 on a Fulfilled order
Trackost had no cost for the product variation when you fulfilled, so the whole price counts as profit. Margin reads 100.0% when the order has no fees, and falls short of that only by the fees. Fulfilling showed 'Recorded with no cost', with the reason:
- 'A product has no batch cost and no recipe. Add a recipe or log a batch.': see Check 1.
- 'A product's stock is valued at zero. Record an adjustment with a cost basis.', 'A product's recipe adds up to zero. Give the recipe's materials a cost.' or 'A product's recipe can't be costed. Check the recipe's components.': see Check 2.
Open Orders and click the order. Read its COGS, True profit and Margin cards.

No cost had reached the product, so the whole price reads as profit. In the lines table below the cards, find the line whose COGS reads $0.00. Its product is the one to check, starting with Check 1.
Check 1: did the product have a cost or a recipe?
- Open Inventory and click the Products tab.
Find the product's row and read its Unit cost. It is the weighted-average cost the sale used, unless a batch or a cost basis has moved it since.

$0.00 means nothing has given the product a cost yet.
$0.00 there means no batch of that variation has been completed and no stock was added with a cost basis, unless its batches themselves cost $0.00 (Check 2). A product that never had a batch or a cost basis had nothing on hand either, so the sale also took its count below zero, as in the picture. That is why the same order shows the 'Untracked production' banner and a Negative stock badge on the line. Negative stock troubleshooting explains the banner.
Such a sale goes out at $0.00 only when the product has no recipe either. With a recipe, it would have been costed from the recipe, and its Unit cost here would show a cost taken from it. The sample Rose Candle has no recipe. Open Recipes to check yours.
Check 2: did the batch or the recipe cost $0.00?
If the product has completed batches, open Production and click the product name on the batch's row to open it. Its Total cost is what its materials cost when it started. $0.00 there means the materials it used had no cost when it started, usually because no purchase or opening stock had been recorded for them yet. Costing troubleshooting covers a material at $0.00.
The batch's Unit cost then holds only labor. It is $0.00 too when no labor rate is set, which is how a new workspace starts, or when the recipe has no labor minutes. Set your hourly labor rate shows where the rate lives. A batch that cost too little makes every sale from its stock cost too little.
A sale costed from the recipe has the same weak spot. Open Recipes and read the product's Unit cost (incl. labor). $0.00 there means its materials have no cost yet and no labor counts. Unavailable means the recipe can't be costed at all, for example because a product it uses has run out and has no recipe of its own.
Check 3: is a line unmatched?
If the order still reads Open after you fulfilled it, one of its lines isn't matched to a product. A line you added as Free text on a new order stays unmatched unless its SKU is exactly the SKU of one of your variations that isn't archived, and no other such variation shares it. An unmatched line has no COGS. Its COGS column reads '—', the order's COGS and True profit cards leave it out, and a banner above the lines reads '1 line unmatched. Trackost matches lines to products by SKU: give the product the same SKU, or match the line here. Its cost isn't tracked until then.'
Fulfilling costs the matched lines and leaves the order Open. Giving one of your variations the line's SKU later matches the line by itself when you save the variation. To finish it by hand instead:
- Open the list in the unmatched line's row, which reads Match a product…, and choose the product variation.
- Click Match. 'Line matched' appears.
Click Fulfill & mark shipped again. The line is costed at the variation's cost at that moment, and the order becomes Fulfilled. The lines you fulfilled before keep their COGS.
Fix the cause
If a sale that went out at $0.00 has to carry a cost, read What doesn't change first. Its procedure starts with a return.
What to record depends on the check that found it:
- Check 1, a product you make: build its recipe and record the purchases its materials are missing, then log the batch you made. Make a batch now walks through it. Recording a purchase needs money access. Without it, ask a team member who has it to record the purchases. On an order you haven't fulfilled yet, the recipe alone is enough: the sale is then costed from it.
- Check 1, a product you buy in: add its stock on Inventory with a Cost basis. The Cost basis needs money access. Without it, ask a team member who has it to add the stock. Add stock with a cost basis walks through it.
- Check 2, a batch or a recipe whose materials have no cost: record the purchases for those materials. Recording a purchase needs money access. Without it, ask a team member who has it to record the purchases. Don't also change the product's cost with Adjust. The next paragraphs say why.
The fix also settles the missing cost, on the units that come after it.
For a product below zero (Check 1), the batch or cost basis that fills the gap charges the units that went out at $0.00 to the units left, which then read above their own cost until they sell. For example, the sample Rose Candle sold 1 at $0.00 and stands at -1. Adding 10 with a cost basis of $60.00 leaves 9 at $6.67 each. The 10 candles still add up to their $60.00, but the missing $6.00 lands on the later sales. The batch or cost basis has to bring the count above zero, or it is refused with, for example, 'This batch doesn't cover what you've already sold. You've sold 1 more than you've made, so add more than 1 in one go.'
For a batch made from materials with no cost (Check 2), those materials had usually never been bought in Trackost, so the batch took them below zero. The purchase you record afterwards fills that gap first. The grams the batch used were costed at $0.00, so the whole purchase is charged to what's left. Wax at -2,000 g, bought as 5,000 g for $50.00, costs $0.0167 a gram afterwards (the page rounds it to $0.02), where you paid $0.01. The material, its recipes and the next batches read above the price you paid until that stock is used, and those batches blend with any $0.00 units still in stock. The first sales are costed too low and the later ones too high, but across them the product's cost adds up to what you spent. At 200 g of wax a unit, 10 made at $0.00 and 15 more at $3.33 come to about $50.00, which is 25 units at $2.00.
The product needs no Adjust of its own, because the purchase already carries the missing cost and the material cost would count twice. To correct the product at once instead, use the two Adjust entries in Why did my unit cost change after a purchase? on the product and on each of those materials, setting each to what its stock cost you.
What doesn't change: the $0.00 already recorded
Trackost never re-costs a fulfilled order. Fixing the cause corrects the sales after it. That one keeps its $0.00, and its profit stays too high in the reports for its period.
If the sale has to carry a cost, the only way is to reverse it and record it again. That works for a product that never had a cost (Check 1). For a batch made from materials with no cost (Check 2), leave the sale as it is. A sale recorded again would be costed at $0.00 again, or, once a new batch is made, at an average that already carries the missing cost, because recording a purchase never changes the product's own cost and the purchases already charge the missing cost to the next batches.
Return the sale. On the order, click Record return. Recording a return needs money access. Without it, ask a team member who has it to make the correction. The form starts with every costed line filled in with all of its whole units. Set every other line to 0, and return only the line that went out at $0.00, all of its units, with restock on and its full refund. A line that went out with its real cost doesn't need returning.
Do the same on every other order that sold this product at $0.00, so its count comes back to zero. With 5 sold at $0.00 and only 1 returned, the count stays at -4, and a batch of 10 at $3.00 would leave 6 at $5.00.
- Fix the cause, as above. With the count at zero, the batch or cost basis sets the product's cost exactly.
Record each returned line again as a new order with Create order, and fulfill it. It is costed at the new cost. Creating an order needs money access. If the first order had fees, leave Fees ($) empty on the new one. A return doesn't take fees back, so they would count twice.
The order doesn't change the result. A restocked return puts the units back at the cost they sold at, here $0.00, and that blends into the product's average. If you have already fixed the cause, return the $0.00 sales the same way and record them again. After a cost basis of $60.00 for 10 and a return of its $0.00 sale, the sample Rose Candle holds 10 at $6.00, and the sale recorded again books $6.00. If some of the product has sold since the fix, those sales already carried part of the missing cost. The sale recorded again then books less than $6.00, and once the product sells out, its sales come to about what its stock cost you.
If the first order came from a connected shop, the new one is a manual order, so the Profit dashboard grouped by Channel lists the sale under Manual and the return under the shop. Connecting a sales channel (Shopify, Etsy or Faire) isn't covered in this help center yet. Email support@trackost.com and we'll walk you through it.
Find every sale that went out at $0.00
There is no filter for it. Open Reports › Orders Margin, choose All time, and go down the COGS column. A fulfilled order that reads $0.00 went out without a cost, and its Margin reads 100.0% if it had no fees. An order that hasn't shipped isn't listed there. The report shows each order as it was fulfilled, before any return, so an order you returned and recorded again still lists its $0.00, next to the new order's row.
An order that also sold other, costed products adds their COGS to its row, so it doesn't read $0.00 there. To catch those, open Orders, search for the product you found in Check 1, open each fulfilled order and read the COGS column of its lines.