A bill of materials is only useful to an assembler if every line can be turned into a real, orderable part. For JLCPCB assembly that means one thing above all: the LCSC part number — the C-prefixed code like C25804 — has to be attached to each component and actually make it into the exported CSV.

Short answer: Add the LCSC C-number as a custom field on each symbol in KiCad, then export the BOM — GUI or kicad-cli — making sure that field is in your export list. The single most common failure is a field that exists on the symbol but was never added to the export set, so the C-number column comes out blank and JLCPCB has nothing to source from.

What a BOM actually needs for assembly

A manufacturable BOM is not a parts dump. At minimum each grouped line needs:

Column Why it matters
Reference Which designators (R1, R2, C7…) the line covers
Value Human-readable value (10k, 100nF, ESP32-S3)
Footprint Confirms the physical package the assembler places
Quantity How many of that part per board
Part number The orderable link — for JLCPCB, the LCSC C-number

Reference, Value, Footprint and Quantity come out of KiCad for free. The part number is the one you have to add deliberately — and the one most likely to go missing.

Add an LCSC part number field to a symbol

In KiCad, any symbol can carry arbitrary custom fields, and that is where the LCSC code lives.

For a single symbol: select it, press E (or right-click → Properties), and in the fields grid click + to add a row. Set the field name (see the naming section below) and paste the C-number as the value.

For a whole design at once, use the Symbol Fields Table (Tools → Edit Symbol Fields Table, or Schematic Editor → the table icon). It gives you a spreadsheet view of every symbol and every field. Add a column for your LCSC field, then fill the C-number down each row. This is far faster than editing symbols one at a time, and it makes gaps obvious — any empty cell is a part JLCPCB can't source.

Save the schematic. The C-number now lives in the .kicad_sch file. Getting it into the BOM is the next step — and it is not automatic.

Group identical parts

You don't want ten separate rows for ten identical 100nF capacitors — you want one line, quantity 10. KiCad groups rows by the fields you tell it to. Grouping by Value and Footprint collapses identical parts into a single line while keeping distinct parts (same value, different package) apart. The Reference column then lists all the designators the line covers. This is standard practice and matches what assemblers expect.

Export the BOM from the GUI

In the Schematic Editor: File → Export → Bill of Materials (KiCad opens the BOM dialog). Choose your columns, set the "Group by" fields to Value and Footprint, pick a preset or format, and export a CSV.

The thing to watch: the export dialog has its own list of columns. If your LCSC field isn't added as a column there, it will not appear in the file — even though the value is sitting right there on every symbol.

Export the BOM with kicad-cli

For anything repeatable — and for a CI pipeline — the headless command is what you want. It reads the schematic directly and writes a CSV with no GUI:

kicad-cli sch export bom --output bom.csv --fields "Reference,Value,Footprint,${QUANTITY},${DNP},LCSC Part #" --group-by "Value,Footprint" --sort-field "Reference" board.kicad_sch

A few things to note:

  • ${QUANTITY} and ${DNP} are KiCad's built-in field tokens — quantity per group, and the Do-Not-Populate flag.
  • LCSC Part # is your custom field. It only produces a populated column if a field by that exact name exists on your symbols.
  • --group-by "Value,Footprint" does the same collapsing as the GUI's group setting.
  • --sort-field "Reference" keeps the output stable revision to revision, which makes diffs meaningful.

Run it, open bom.csv, and confirm the LCSC column is actually full. If it's empty, the field name didn't match — which is the trap worth its own section.

The field-name problem (the part everyone gets wrong)

Here is the insight that saves the most rework: there is no single canonical name for the LCSC field, and the name you choose has to match in two places at once — the symbol and the export list.

The LCSC/JLCPCB part number gets stored under all sorts of names in the wild. JLCPCB's Fabrication Toolkit is deliberately forgiving and will look for the C-number under any of these:

Accepted field names
LCSC
LCSC Part #
LCSC PN
LCSC P/N
LCSC Part Number
JLCPCB
JLCPCB Part #
JLCPCB PN
JLC
JLC Part #
MPN

Any one of them works on JLCPCB's side. The problem is entirely on the KiCad export side. Two ways it bites:

  1. Name mismatch. Your symbol carries the value under LCSC PN, but your kicad-cli --fields list (or the GUI column set) asks for LCSC Part #. KiCad doesn't warn you — it just emits an empty column. The C-number silently goes missing and you find out when JLCPCB says the part is "not found."
  2. Field never exported. The field is on the symbol under a perfectly good name, but it simply isn't in the export list at all. Same outcome: blank column.

The rule to internalise: whichever field name you use, that exact name must appear in your export field list, or the C-number never reaches the CSV. Pick one name, use it consistently on every symbol, and put that same string in your --fields. Then verify the column is populated before you upload — a BOM that looks complete but has an empty part-number column is worse than an obvious error, because it slips through to the assembler.

Once the CSV is right, it pairs with the placement file for assembly — see how to export a pick-and-place / CPL file from KiCad for the other half of the JLCPCB assembly package.

Let the pipeline handle the field-name trap

Getting this right by hand, every revision, on every board, is exactly the kind of quiet, repetitive chore that eventually bites. This is where an automated pipeline earns its keep.

GoForFab runs kicad-cli on every push and exports your BOM under every supported LCSC/JLCPCB field name at once — LCSC, LCSC Part #, JLCPCB, JLC, MPN and the rest — so whichever name your symbols happen to use, the C-number always lands in the CSV. No blank columns, no silent drops, no re-uploading a "not found" BOM. It's free forever, and it means the field-name trap stops being something you have to remember. Connect a KiCad project and every revision ships a manufacturing-ready BOM with the part numbers intact.