Okay, after a lot of trial & error I figured this one out. Here's what the options displays
opts =
quadprog options:
Options used by current Algorithm ('trust-region-reflective'):
(Other available algorithms: 'interior-point-convex')
Set properties:
Algorithm: 'trust-region-reflective'
OptimalityTolerance: 1e-10
Default properties:
Display: 'final'
FunctionTolerance: 'default dependent on problem'
HessianMultiplyFcn: []
MaxIterations: 'default dependent on problem'
StepTolerance: 2.2204e-14
SubproblemAlgorithm: 'cg'
TypicalX: 'ones(numberOfVariables,1)'
In particular,
FunctionTolerance: 'default dependent on problem'
Setting OptimalityTolerance and NOT FunctionTolerance must short-circuit setting FunctionTolerance so it is trying to take sqrt('default dependent on problem') instead of sqrt([default value]). To me this seems like a bug but perhaps someone can explain why it's intended behavior.
The workaround (of course) is to also set FunctionTolerance.
Best Answer