Quality & Process Control

Why Units Pass the Bench but Fail in the Field

Learn why units pass production test but fail in the field: coverage gaps, wide limits, intermittent faults, and how to feed returns back into the test.

JJulien Buteau
intermediate9 min readOctober 27, 2026

A unit that passes every production test and then fails at the customer means the test did not exercise the condition that broke it, or measured it and let it through. Learn the four usual causes (coverage gaps, limits too wide, intermittent faults, measuring the wrong thing), how to tell them apart, and how to feed each field return back into the test with TofuPilot.

Symptoms and Likely Causes

SymptomLikely causeSection
Returned unit passes the production test again on the benchTest conditions differ from use: load, vibration, temperature, durationCause 1
Returned unit's original results were inside limits but far from the populationLimits too wideCause 2
Failure cannot be reproduced, or appears and disappearsIntermittent fault, measured only at restCause 3
Test reports pass on a function that does not work in useThe measurement is a proxy that does not represent the functionCause 4
Several returns share a lot, a date range or a stationProcess change that the test does not coverCause 1 or 2, then the line

The first check on any return is the same: find the unit's original test results by serial number. Without that history, every cause above is a guess.

Cause 1: The Test Runs Under Conditions the Unit Never Sees in Use

A bench test is usually static and short: nominal supply, room temperature, no load or a light load, a few seconds per measurement. Use is dynamic and long. A defect that only appears under one of the use conditions passes the bench.

ConditionBench testUseDefect that only shows in use
CurrentNo load or light loadFull load, peaks, regenerative transientsResistive joints and crimps, undersized traces, MOSFETs with poor attach
VibrationNoneContinuous, broadbandCracked joints on heavy parts and wires, connectors, loose hardware
TemperatureAmbientCold starts, hot enclosures, cyclesMarginal components, solder fatigue, timing margins
DurationSecondsHoursThermal runaway, slow drift, wear
TransitionsSteady setpointsSteps, starts, stopsInrush, overshoot, bus overvoltage on deceleration

An example from motor and ESC testing shows the size of the gap. On a measured bench, a 3115-size brushless motor without a propeller drew 3.5 to 4.5 A at full throttle on a 6S pack. With a typical propeller, the same motor is estimated to draw 60 to 80 A at full throttle. A no-prop test therefore exercises the power path at about 4 / 70 ≈ 6% of its use current. A joint that is resistive enough to overheat at 70 A dissipates I²R, so (4 / 70)² ≈ 0.3% of that power at 4 A, and passes. See motor and actuator testing for loaded test setups.

What to Do

  • List the use conditions for the product and mark which ones the production test covers.
  • For each uncovered condition, decide between adding it to the test (a load, a vibration step, a temperature point) and covering it with a screen such as random vibration or thermal cycling.
  • Do not try to cover use conditions by overstressing. A current far above use, applied to "burn out" weak joints, is destructive and degrades the good joints too.

Cause 2: Limits Too Wide

Limits copied from a datasheet, or widened to stop false failures, can pass units that are clearly abnormal compared to the population. A unit at the edge of a wide limit is often the one with a defect.

Compare the returned unit's original measurements to the distribution of all units of the same part:

Returned unit positionInterpretationAction
Near the center of the distributionTest did not see the defectCoverage gap: Cause 1, 3 or 4
In the tail, inside limitsTest saw an abnormal value and passed itTighten the limit toward the population
Outside limitsUnit should have failedCheck for retest after failure, overrides, or a limit changed after the run

In TofuPilot, every measurement has a control chart and a Cpk across runs. Placing the returned unit's value on that chart answers the question in one look. For the method to set limits from the distribution rather than the datasheet, see how to set measurement limits using production data, and for monitoring drift over time, what SPC is.

Cause 3: Intermittent Faults Measured at Rest

A cold or cracked solder joint can read a normal resistance at rest, because the cracked surfaces still touch. It opens under vibration, flexing or thermal expansion. A single reading at rest passes it every time.

Measure the same quantity while the unit is disturbed, and record the variation, not one value:

  • Vibrate, tap or flex the assembly during the measurement.
  • Sample continuously and record the maximum deviation from the mean, not only the mean.
  • Use a 4-wire (Kelvin) connection for low resistances: separate force and sense contacts, otherwise the probe contact resistance dominates and its own variation hides the joint.

The phase below samples a joint resistance while a shaker runs, and records the mean and the peak deviation:

procedure.yaml
28 lines
name: Power Lead Joint Checkversion: 1.1.0plugs:  - name: Shaker Controller    key: shaker    python: plugs.shaker:ShakerController  - name: Micro-ohmmeter    key: ohmmeter    python: plugs.ohmmeter:MicroOhmmetermain:  - name: Battery Lead Resistance Under Vibration    python: phases.joint_vibration:joint_vibration    timeout: 5m    with:      duration_s: 60    measurements:      - name: Joint Resistance Mean        unit: mΩ        validators:          - operator: "<="            expected_value: 0.8      - name: Joint Resistance Max Deviation        unit: mΩ        validators:          - operator: "<="            expected_value: 0.1
phases/joint_vibration.py
20 lines
import statisticsimport timedef joint_vibration(shaker, ohmmeter, measurements, log, duration_s):    samples = []    shaker.start()    try:        deadline = time.monotonic() + duration_s        while time.monotonic() < deadline:            samples.append(ohmmeter.read_milliohm())            time.sleep(0.05)    finally:        shaker.stop()    mean = statistics.fmean(samples)    deviation = max(abs(s - mean) for s in samples)    log.info(f"{len(samples)} samples, mean {mean:.3f} mOhm, max deviation {deviation:.3f} mOhm")    measurements.joint_resistance_mean = mean    measurements.joint_resistance_max_deviation = deviation

The limits and duration are example values. A good joint gives a stable reading under vibration; a cracked one shows spikes, which the deviation measurement catches even when the mean stays normal.

Cause 4: Measuring the Wrong Thing

A test can measure something easy that correlates with the function on good units and does not on defective ones.

Proxy measurementWhat it missesMeasurement that represents the function
Motor spins (boolean)Excess current, rough commutation, a weak phaseCurrent and speed at defined throttle points, per phase
Voltage present on a rail at no loadRail collapse under loadRail voltage at rated load current
Communication link responds onceError rate over timePacket count and error count over a fixed duration
Visual check of a jointInternal crack, insufficient wettingJoint voltage drop at a known current, compared to a golden unit

Record values, not booleans. A boolean pass hides how close the unit was to failing, and gives nothing to compare a return against.

Feed Field Returns Back Into the Test

Each return is a test case the production test failed. The loop below turns it into a change in the test.

  1. Identify the unit by serial number and open its test history. In TofuPilot, every run is stored against the unit serial number, with each measurement, its limits, the station and the procedure version.
  2. Record the return analysis as a run on the same serial number. Run the production procedure, or a dedicated failure-analysis procedure, on the returned unit, and mark it with run metadata so these runs can be filtered:
phases/mark_return.py
def mark_return(run):    run.metadata["context"] = "field_return"    run.metadata["rma"] = "RMA-0001"  # your return reference
  1. Classify the cause with the tables above: coverage gap, limit too wide, intermittent, wrong measurement.
  2. Change the test: add the measurement or the condition, or tighten the limit. Bump the procedure version, which is recorded with every run, so results before and after the change can be compared.
  3. Verify on the returned unit. The changed test must fail the returned unit. If it does not, the change does not address the defect.
  4. Watch the production data. A new measurement or a tighter limit lowers first-pass yield at first. Check the failure Pareto to confirm that the new failures are the defect, not the test. If yield falls in an unexpected way, see why yield drops.

Common Pitfalls

Closing a return as "no fault found" after one bench test. The bench test is the test that already passed the unit. Reproduce the use conditions before concluding.

Widening limits to reduce false failures without looking at the distribution. It also lets through the units in the tail, which are the likely field failures.

Recording booleans instead of values. A return cannot be compared to a population that was never measured.

Overstressing to compensate for missing coverage. High current or extreme stress applied to every unit damages good units. Use screens with levels set not to consume good-unit life.

Changing the test without verifying it on the returned unit. Without that check, nothing shows the new test would have caught the failure.

Key Points

  • Start every return investigation from the unit's original results, found by serial number.
  • Bench tests are usually static and short; failures in use come from load, vibration, temperature, duration and transitions.
  • A returned unit in the tail of the distribution points to limits that are too wide; one near the center points to a coverage gap.
  • Intermittent faults need measurement during vibration or flexing, recorded as variation, with Kelvin connections for low resistances.
  • Measure the function, record values, and feed each return back as a test change verified on the returned unit.

More Guides

Put this guide into practice