Root cause
const getEffortScale = (effort: number) => Math.max(effort, 1e-2)
Math.max(undefined, 1e-2) is NaN. When effort is undefined, every MAX_ITERATIONS: Math.ceil(N * getEffortScale(effort)) becomes NaN, and the solver reports TinyHyperGraphSolver ran out of iterations on the first step (the iterations >= NaN guard).
When effort is undefined
TinyHypergraphPortPointPathingSolver runs the DuplicateCongestedPortSolver prepass when params.connections.length <= MAX_CONNECTIONS_FOR_DUPLICATE_CONGESTED_PORT_PREPASS, and passes getEffortScale(params.effort):
MAX_ITERATIONS: Math.ceil(10_000_000 * getEffortScale(params.effort)),
AutoroutingPipelineSolver4 defaults its own this.effort = mutableOpts.effort ?? 1, but that default is not threaded into HgPortPointPathingSolverParams.effort, so params.effort here is undefined. Boards with few connections (which hit the prepass) therefore NaN out; larger boards that skip the prepass are unaffected (e.g. the dataset-srj15 sample11 fixture passes, masking this).
Symptom
A small/low-connection 2-layer board that should route in seconds instead fails immediately with ran out of iterations, 0 traces produced.
Repro
Math.max(undefined, 1e-2) // => NaN
Route any board whose connections.length is under the prepass threshold with no explicit effort; it instant-fails. Forcing getEffortScale to floor undefined to a real number (Math.max(Number(effort) || 1, 1e-2)) makes the same board route.
Fix options
- Make
getEffortScale undefined-safe: Math.max(Number(effort) || 1, 1e-2), or
- Thread
AutoroutingPipelineSolver4.effort into HgPortPointPathingSolverParams.effort (and the other params objects) so it is never undefined.
Root cause
Math.max(undefined, 1e-2)is NaN. Wheneffortis undefined, everyMAX_ITERATIONS: Math.ceil(N * getEffortScale(effort))becomesNaN, and the solver reportsTinyHyperGraphSolver ran out of iterationson the first step (theiterations >= NaNguard).When effort is undefined
TinyHypergraphPortPointPathingSolverruns theDuplicateCongestedPortSolverprepass whenparams.connections.length <= MAX_CONNECTIONS_FOR_DUPLICATE_CONGESTED_PORT_PREPASS, and passesgetEffortScale(params.effort):AutoroutingPipelineSolver4defaults its ownthis.effort = mutableOpts.effort ?? 1, but that default is not threaded intoHgPortPointPathingSolverParams.effort, soparams.efforthere isundefined. Boards with few connections (which hit the prepass) therefore NaN out; larger boards that skip the prepass are unaffected (e.g. thedataset-srj15 sample11fixture passes, masking this).Symptom
A small/low-connection 2-layer board that should route in seconds instead fails immediately with
ran out of iterations, 0 traces produced.Repro
Route any board whose
connections.lengthis under the prepass threshold with no expliciteffort; it instant-fails. ForcinggetEffortScaleto floor undefined to a real number (Math.max(Number(effort) || 1, 1e-2)) makes the same board route.Fix options
getEffortScaleundefined-safe:Math.max(Number(effort) || 1, 1e-2), orAutoroutingPipelineSolver4.effortintoHgPortPointPathingSolverParams.effort(and the other params objects) so it is never undefined.